SIMPLE TCP... possible?...[SOLVED]

Is the following possible?

I want an Arduino + W5100 shield to be a simple server... not WEB server, that is to say I don't expect the "fancy" bits... I JUST want....

A device that will sit on the LAN and watch for incoming attempts from clients to "connect".

Once the ("socket"? is that the right term?) channel between server (the Arduino) and client is in place, if the client sends JUST two bytes ($BB $83 would be PERFECT) to the server, it should respond with just a string of bytes. For the sake of arguement, it would be nice if it responded with the following. (The following may be trivial, but I mention it just in case.)

$BB $82 $01 $01 $FF $FF

Note: The second $FF is an end of record marker, but $FF can also occur in the line.

Furthermore, the line can also be...

$BB $82 $02 $01 $FF $02 $00 $FF

As you see,that's a different length, but the third byte in the string tells you how long it should be.

(End of possibly trivial bit)

I have a Windows program which will do Good Things as a client if such a server is present... so if you feel like having a play with the code to accomplish the above, the software to test your efforts exists. It is TCP002.exe in the zip file you can download from

http://sheepdogguides.com/zips/TCP001.zip

$50 to a reputable US or UK charity if someone who is at least "two star" in this forum says he has the finished code done, and working with TCP002. That contribution payable to the charity BEFORE you deliver the code to me, copyright free. (You propose the charity. I decide if it is "reputable"... I WILL give to "Save The Children", if we can't agree on another closer to your heart. Someone who would know once told me that their field workers tend to stay in more modest hotels than the one's sometimes used by those of other NGOs.)

Failing anyone interested in actually writing the code... can anyone give an encouraging "It shouldn't be a big deal" answer?

Oh! Ideally, the code should allow multiple concurrent connections to the server, but if that's going to be a Big Pain, then, as long as I know the problem exists, it is acceptable if the server can only handle one connection at at time, and subsequent petitioners just find that they can't connect. (If they could somehow be TOLD "the line is busy" (vs the server is down), that would be good... but I suspect that a connection ("socket"?) would be needed to say "no connection possible"... Catch-22? A simple failure (by the server) to respond to an attempt to connect by a client is adequate, if not wonderful.

Thanks for considering!!

You can do that. I use the Arduino as a client, and a Linux box as a "server". Not a web server. Pick a port like 8081.

Here is the important stuff. This would be a sample "request". The server would return something very similar. Note the double 255's. That is your EOF.

char outBuffer[4];

outBuffer[0] = 69;
outBuffer[1] = 70;
outBuffer[2] = 255;
outBuffer[3] = 255;

client.write(outBuffer,4);

Add: It would be up to you to insure that double 255's do not occur in the data.

Sounds like about three minutes work to me...

Thanks, Surfer, but I need Arduino as server, not the other way around, and I WILL have $FFs in data portion of record.

Thanks, KE7GKP... I've done SNMP... and it isn't what I want here.

Thank you Fungus... do the work and the money goes to your charity, or Save The Children, if we can't agree on someone else! Tom

The other way around is not a problem. It works the same. You need to "build" a client program like my server program on your Linux or Windows box. A web browser won't do it.

If there is the possibility that you will have 2 0xFF in a row in the data, you better find another way to determine EOF.

Hint:

byte outBuffer[8];

outBuffer[0] = data0;
outBuffer[1] = 0;
outBuffer[2] = data1;
outBuffer[3] = 0;
outBuffer[4] = data2;
outBuffer[5] = 0;
outBuffer[6] = 0xFF;
outBuffer[7] = 0xFF;

If there is the possibility that you will have 2 0xFF in a row in the data, you better find another way to determine EOF.

Is it possible to "watch" the data coming in, byte by byte? Is there something like the "available" function which I am familiar with when communicating over a serial comms channel?

Yes, there is.

tkbyd:
Thank you Fungus… do the work and the money goes to your charity, or Save The Children, if we can’t agree on someone else!
Tom

Ok, I prefer Oxfam…

Here’s the code:

//
// TEMPerLAN sensor emulator for Arduino by Fungus
//
// This code is in the public domain...
//

#include <SPI.h>
#include <Ethernet.h>

// Enter MAC address and IP address for your Ethernet shield
// The MAC should be printed on your shield
// The IP address will be dependent on your local network
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,100,0xAD };

// Server is on port 23 (telnet) because that's the default in TCP002.exe
Server server(23);

void setup() {
  // Initialise the W5100 Ethernet chip
  Ethernet.begin(mac, ip);

  // Start the serial library (for debug output)
  Serial.begin(115200);
  
  // Start the TCP server
  Serial.print("Opening server...\n");
  server.begin();
}

void loop()
{
  Client c = server.available();
  if (c.connected()) {
    Serial.print("Incoming connection!\n");
    // Read two bytes from client
    byte b1 = c.read();
    byte b2 = c.read();
    // Debugging: Show me what the client sent
    Serial.print("The client said 0x");
    Serial.print(b1,HEX);
    Serial.print(" 0x");
    Serial.print(b2,HEX);
    Serial.print("\n");
    // Deal with the connection
    if ((b1 == 0xBB) and (b2==0x82)) {
      // nb. Maximum size of response is 68 bytes (enough for 32 sensors)
      byte response[68];
      // Create a response
      byte *r = response;
      *r++ = 0xBB;
      *r++ = 0x82;
      *r++ = 0x01;
      *r++ = 0x01;
      *r++ = 0xFF;
      *r++ = 0xFF;
      // Send it
      c.write(response,r-response);
      // Close the connection
      c.stop();
    }
  }
}

Brilliant! I knew it had to be simple… wish I’d realized HOW simple!!!

As soon as I have a chance to check all is well, Oxfam will hear from me, and I’ll arrange some form of confirmation for you!

Thank you!

Tom

I just spotted a bug, the “c.stop()” should be outside the if() or it won’t close the connection.

(Apparently the people who write that library haven’t heard of destructors…)

Here’s a new version…

//
// TEMPerLAN sensor emulator for Arduino by FTB
//
// This code is in the public domain...
//

#include <SPI.h>
#include <Ethernet.h>

// Enter MAC address and IP address for your Ethernet shield
// The MAC should be printed on your shield
// The IP address will be dependent on your local network
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,100,0xAD };

// Server is on port 23 (telnet) because that's the default in TCP002.exe
Server server(23);

void setup() {
  // Initialise the W5100 Ethernet chip
  Ethernet.begin(mac, ip);

  // Start the serial library (for debug output)
  Serial.begin(115200);
  
  // Start the TCP server
  Serial.print("Opening server...\n");
  server.begin();
}

void loop()
{
  Client c = server.available();
  if (c.connected()) {
    Serial.print("Incoming connection!\n");
    // Read two bytes from client
    byte b1 = c.read();
    byte b2 = c.read();
    // Debugging: Show me what the client sent
    Serial.print("The client said 0x");
    Serial.print(b1,HEX);
    Serial.print(" 0x");
    Serial.print(b2,HEX);
    Serial.print("\n");
    // Deal with the connection
    if ((b1 == 0xBB) and (b2==0x82)) {
      // nb. Maximum size of response is 68 bytes (enough for 32 sensors)
      byte response[68];
      // Create a response
      byte *r = response;
      *r++ = 0xBB;
      *r++ = 0x82;
      *r++ = 0x01;
      *r++ = 0x01;
      *r++ = 0xFF;
      *r++ = 0xFF;
      // Send it
      c.write(response,r-response);
    }
    // Close the connection
    c.stop();
  }
}

There is a version that reads chars and not bytes ? thx :)

Dear Fungus...

Realizing it would be a while before I could test the code you sent (my present Arduino+ethernet is tied up with something I don't want to disturb.... I've ordered another, for your code. Throw money at a problem? Moi? Sigh...)... I decided it wasn't fair to hold up the payment to Oxfam due to delays not of your making, so it will go out today. I've asked for a receipt. We'll see. If they send it, I can send a copy on to you, if you'll let me know where, via....

http://sheepdogsoftware.co.uk/ctact.htm

Oh!! And thank you for catching the "c.stop()" thing!

PS: ARGH!!! Just as I was putting the envelope in the mailbox, I realized I written the check for GPB50, not the dollar equivalent! Bah! Oh well... Oxfam does good work, although I prefer (Doctors Without Borders, IRC and Americares for similar work... at least two of them got into Gaza promptly when Israel went postal.)

=== Dear Dampe,

One of us is missing something.... if you have a "byte", you have the char, don't you? It is just a case of being careful what you do with it. E.g., if you have received $41, there is no harm in sending it to the serial monitor, because it will either come out as $41, 65, or "A", depending on how you send it. If you have $10, on the other hand, that is not a printable character, so if sent to the serial monitor the way the $41 was, it will cause confusion... minor confusion, in the case of $10, but I wouldn't want to say what some other possible bytes would do, if sent as characters.

I hope someone more fluent will join this discussion and either shoot down my answer, or provide details for Dampe and others of how you "send to the serial monitor to result in "65", and how to send to result in "A".

I'm sorry that the code I needed involved a bunch of things that are not good candidates for the serial monitor. If you want to adapt it, you can change....

      *r++ = 0xBB;
      *r++ = 0x82;
      *r++ = 0x01;
      *r++ = 0x01;
      *r++ = 0xFF;
      *r++ = 0xFF;

... to...

      *r++ = 0xBB;
      *r++ = 0x41;
      *r++ = 0x42;
      *r++ = 0x43;
      *r++ = 0x44;
      *r++ = 0x45;

... and THAT should give rise to ABCDE, even if sent to the serial monitor in the way that gives rise to the ASCII associated with certain bytes.

tkbyd:
One of us is missing something… if you have a “byte”, you have the char, don’t you? It is just a case of being careful what you do with it. E.g., if you have received $41, there is no harm in sending it to the serial monitor, because it will either come out as $41, 65, or “A”, depending on how you send it.

It’s eight bits of data. The bits don’t change because you look at them from a different angle.

Char or byte, the same eight bits will be sent to the serial monitor. What the serial monitor does with them is up to the serial monitor.

"byte" is gone from Arduino 1.0 (good riddance! Environments shouldn't predefine such likely variable names, especially when there is so little reason to do so! BYTE and xxx.print(a, BYTE) are also gone.)

BYTE is gone? GREAT!! I say "viva new data types!" How about this? 8bit 16bit 32bit ...and drop all else. No byte, int, char, etc.

Add: That is why I enjoy working with the source code. I like working with uint8_t and uint16_t data types. :)

The simple server is working!!!

Full code, full tutorial at...

http://sheepdogguides.com/arduino/art5simpsrv.htm

My thanks to Hobbytronics.co.uk for exceedingly efficitent supply of a Sparkfun Ethernet Pro, which is where the software is running.

Now... ArduSimpSrv is a very simple TCP/IP server... but it is SO simple that you can't "talk" to it with a browser or with telnet. But neither do you run into the "page too big" problem as quickly.

How DO you talk to it? Via a specially written client program. Full details in a tutorial linked to the tutorial cited, and a compiled version of the software is available (free) for Windows. Again... details in pages given. If some Linux person would like to provide the Linux equivalent, I would be delighted.

SO FAR all ArduSimpSrv does is watch for an incoming $BB $82 command, and respond with an unchanging response. Adding the ability to process more meaingful commands is trivial, and will be done soon. With those commands, you will be able to turn and LED on the ArduSimpSrv on or off, and you will be able to read the value on one of the analog ports, which, for demonstration purposes will be fed by a light detector the LED will shine on.

If you want to "play" with an ArduSimpSrv, there will probably be one on....

http://mon7nc.dyndns.org:5202/

(Oops.... For a few hours that read ...242. The device is at 192.168.0.242, but the PORT, whihch is what you needed, is 5202... Sorry.)

... at least for the rest of October 2011... but remember you need the special client software to access it. (If you know of another way, using freeware or shareware with reasonable free trial terms, or basic system utilities, I would be delighted to know of it!)

The need for special client software is a pain... but the basic idea in ArduSimpSrv opens up all sorts of possibilities to those who can be bothered with the writing of the client software for the needs of their application.

An instance of the ArduSimpSrv discussed above is now online at the address given previously...

mon7nc.dyndns.org

You have to use the purpose written client Windows software to access it... available in a zip at...

http://www.sheepdogguides.com/zips/TCP006.zip

... which has just the .exe you need.

When you have that running, you fill in the URL above, and specify port 5202...

Once you've done that, you can...

Turn LED on or off See that it went on or off by subsequently reading the value on the ArduSimpSrv's AnalogIn1 See how many requests have been served by the server since it was last reset.

You CAN... and feel free to test the facility... tell it to read the AnalogIn1 input repeatedly, as often as once per second... but after you've had a little play, please turn that off again, make room for other visitors?

I'm not quite ready for details of your experiences yet, but if you try it and it Just Doesn't Work, I need to know that!! (^_^)

Hope it amuses.