Hi,
I just downloaded UIPEthernet and put it to use to test tcp socket. I provide my code and questions to hopefully have your comments, because with little knowledge I have in socket programming, easily can kill my little Arduino robot
I loaded this test program from included examples:
#include <UIPEthernet.h>
EthernetServer server = EthernetServer(1000);
void setup()
{
 Serial.begin(9600);
 uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};
 IPAddress myIP(192,168,0,6);
 Ethernet.begin(mac,myIP);
 server.begin();
}
void loop()
{
 size_t size;
 if (EthernetClient client = server.available())
  {
   while((size = client.available()) > 0)
    {
     uint8_t* msg = (uint8_t*)malloc(size);
     size = client.read(msg,size);
     Serial.write(msg,size);
     free(msg);
    }
   client.println("DATA from Server!");
   client.stop();
  }
}
One issue is that the 'size' there in IDE is in different color and seems to be a reserved one, so I changed the loop and added a processing function this way:
void loop()
{
  size_t msgsize;
 if (EthernetClient client = server.available())
  {
   while(client){
   while((msgsize = client.available()) > 0)
    {
     uint8_t* msg = (uint8_t*)malloc(msgsize);
     msgsize = client.read(msg,msgsize);
     for(int i=0;i<msgsize;i++){
     receiverchar((char)(*(msg++)));
     }
     free(msg);
    }
   }//while(client){
  }
}
void receiverchar(char c)
{
  Serial.println(c);//a simple test
}
After getting the correct base code, I will then develop from receiverchar on.
Now some questions please:
Is the while(client) I use to keep the connection alive is the correct approach?
the initial example has client.stop(); but as I need to constantly command the robot (by wifi, from Android phone to enc28j60, to Arduino), so I don't want to close the connection. Is it a must or it is in example simply as an example!?
I tried the code and after a while it closes socket automatically as usual. As I understand, I should not do anything for this in Arduino code, but to change my java code of Android to keep the socket alive right? Or any better approach exists please?
Is my code with:
     for(int i=0;i<msgsize;i++){
     receiverchar((char)(*(msg++)));
     }
look correct? I'm thinking if it could pass off the end of msg pointer and mess with memory? Maybe a better approach you could kindly suggest please?
Is the while(client) I use to keep the connection alive is the correct approach?
There is nothing about testing the address of an object, as you are doing, that will keep the connection alive.
while(27) does the same thing as while(client). Not much, that is.
the initial example has client.stop(); but as I need to constantly command the robot (by wifi, from Android phone to enc28j60, to Arduino), so I don't want to close the connection. Is it a must or it is in example simply as an example!?
Does that code even work with the enc28j60 hardware?
Is my code with ... look correct? I'm thinking if it could pass off the end of msg pointer and mess with memory? Maybe a better approach you could kindly suggest please?
Yes. It's fine. Since you test how much data is available, allocate that much space, and then read only that number of characters, you won't walk off the end of the array.
Of course, I have to wonder why you don't use char as the type.
There is nothing about testing the address of an object, as you are doing, that will keep the connection alive.
Sorry to ask, if this won't make a lot of trouble, could you please point me to an example or tell me the command to test the address? I don't know how to do it with this lib.
Does that code even work with the enc28j60 hardware?
Yes. I have no other choice right now. I had a different setup but burned a part out and ordered a new one, now waiting. Until it comes, I thought to put the robot to use by this enc28j60 so "use it or lose it" don't want to lose my Arduino
So, please, am I right in guess: this client.stop(); was in the initial code just for example, not a must, true?
When you compile code, all names are changed to addresses. client is the name of a variable that contains an instance of the EthernetClient class. while(client) become while(some_address). Testing the address that way makes no sense. It does not make sure that the instance at that address does anything, like keep a connection open.
So, please, am I right in guess: this client.stop(); was in the initial code just for example, not a must, true?
The client.stop() statement is how the client instance tells the hardware that it no longer needs the connection to the server (which may have already closed it's end of the connection).
Considerably different code is needed on the client and on the server for persistent connections. I've never used that model. All the stuff I want to do is true client/server communication, where a new connection is opened for every exchange of data.
Thanks now clear, I first thought there is some command in this library that I don't know, with which I can make an IP address query of the other end of connection and help to keep the connection alive in case of non-active communication.
So to conclude this, you mean there is no definite room to improve the state of keeping active connection for a long time? The problem I'm facing is this:
my arduino robot has simple commands of B,F,L,R,S for navigation.
suppose I use the true client / server with new connection every time
I command F, robot moves forward, connection is closed by Arduino software (as in example)
robot has an obstecle in front and I command S to stop it but the new connection takes time to get open!
Thanks now clear, I first thought there is some command in this library that I don't know, with which I can make an IP address query of the other end of connection and help to keep the connection alive in case of non-active communication.
all commands in UIPEthernet are suppost to behave the same as in stock Ethenet-lib. If you find any different behaviour in UIPEthernet, please file an issue against UIPEthernet-library on Github
There's absolutly no need to close the connection with stop() every time loop called. All you have to do is keep the connected client-instance in a variable you declare outside of loop. Calling stop() on client-instance is mandatory if the instance is local to the loop-method as it goes out-of-scope when loop returns leaving the tcp-stacks internal memory for that connection allocated.
See EthernetClientStream.cpp for some code that does what you ask for.
Thank you Norbert,
Now things much more clear. I have a last question:
I tested my code many times (absolutely based on server example coming with the library), all works fine. There is one issue only. I use a java client program on my Android that opens the socket and sends the commands when I click a button there. If I click with a 2 seconds pause, all is ok. If I command fast (click one after the other without pause), sometimes it halts and I need to restart Arduino. If it halts, even pinging is impossible which means that it is a halt from Arduino side. I can not figure it out why the halt happens and code is bare bone simple. I'm just testing library. Could you please suggest something?
I suspect your java-library doesn't close the sockets fast enaught when clicking to fast. UIPEthernet does handle 4 connections simultaniously and will not respond to further connection-request if these are used up. I suggest you make use of a packet-sniffer like wireshark to debug what packages Andriod aktually does send (it's also possible to export packets grabbed with wireshark so I could have a look ans see what is happening on your side). This way you can know for sure whether your Android-program behaves well (closing the connections by sending FIN-packets to arduino) or not.
Thanks for pointing to the tracing technique, I will download wireshark and send results when ready.
In fact I am quite happy with this nice library. I read online that enc28j60 is cheap and won't keep a healthy socket. My robots had their original parts dead and waiting for new parts from China and I must run them (for photogiff.kiev.ua and ekoklimat.com.ua). I decided to temporarily use Arduino+enc28j60 - what I had available. Now I feel I stay with them even when new parts arrive! You see robots in attachment (one with camera head, called Photogiff and the other with air conditioner called Ekoklimat).
My client Android - now working on actionscript for nice interface - never closes the socket. It opens one, right when creation-complete event is issued, then use it all the time. The problem is that if it closes the socket after commanding, it costs a (nearly) 3 seconds (I'm on atmega328) to open a new one.
I greatly appreciate any suggestion on this "to close socket after each command or not to".
That code is a wrapper around EthernetClient that looks like a regular Stream (from outside) and internally tries to stay connected to a remote socket including automatic reconnect whenever the connection is lost.
You can detect the 'connection is lost'-state by checking the return-values of write().