TCP socket Events

01 Mar 2011

Hello, I´m working with the "TCPSocket.h" I use the function "setOnEvent" and I wait for the event : "TCPSOCKET_READABLE". When this event happens, I try to receive data using "recv" but I don´t receive anything. I don´t understand how the event "TCPSOCKET_READABLE" works. Is supposed that if the events occurs, there are some data in a buffer. But What kind of buffer? I mean, when "the other side" of the communication sends something to my socket, is stored in that buffer and then the event occurs??

Thank you and regards,

María.

01 Mar 2011

Do you do a Net::poll() call? The event tells you 'there is data available', but this call transfers it to the buffer of the TCPSocket class (IIRC).

02 Mar 2011

Yes, I do the call. So the buffer is on TCPSocket class. The event means that there is data available where? on the buffer of TCPSocket class?? Thanks!

02 Mar 2011

The received data is in a buffer soemwehere in the network stack. You need to have your own buffer, which you the give as parameter in the recv() call. recv() then tells you the number of bytes which are available. As an example, look at th TCPLineStream class (but this class doesn't to the recv() call in the event handler).

02 Mar 2011

Thank you. And does anybody knows why (if the TCPSOCKET_READABLE event occurs) when I do the recv, I don´t receive anything?? Thank you so much

18 Mar 2011

This might be of some help.

Import program

00001 
00002 // TCP Echo server
00003 // 2010/9/7
00004 
00005 
00006 /*
00007 
00008 (Execute Sample)
00009 PC side:
00010 telnet 192.168.0.25 12345
00011 Trying 192.168.0.25...
00012 Connected to 192.168.0.25.
00013 Escape character is '^]'.
00014 
00015 mbed side:
00016 Setup OK
00017 mbed IP Address is 192.168.0.25
00018 Binding..
00019 Listening...
00020 Listening: TCP Socket Accepted
00021 Listening: Incoming TCP connection from 192.168.0.7
00022 TCP Socket Readable
00023 Received&Wrote:test text
00024 
00025 TCP Socket Writable
00026 
00027 
00028 */
00029 
00030 #include "mbed.h"
00031 #include "EthernetNetIf.h"
00032 #include "TCPSocket.h"
00033 
00034 DigitalOut led4(LED4, "led4");
00035 
00036 // EthernetNetIf eth;
00037 EthernetNetIf eth(
00038   IpAddr(192,168,0,25), //IP Address
00039   IpAddr(255,255,255,0), //Network Mask
00040   IpAddr(192,168,0,1), //Gateway
00041   IpAddr(192,168,0,1)  //DNS
00042 );
00043 
00044 #define TCP_LISTENING_PORT 12345
00045 
00046 TCPSocket ListeningSock;
00047 TCPSocket* pConnectedSock; // for ConnectedSock
00048 Host client;
00049 TCPSocketErr err;
00050 
00051 void onConnectedTCPSocketEvent(TCPSocketEvent e)
00052 {
00053    switch(e)
00054     {
00055     case TCPSOCKET_CONNECTED:
00056         printf("TCP Socket Connected\r\n");
00057         break;
00058     case TCPSOCKET_WRITEABLE:
00059       //Can now write some data...
00060         printf("TCP Socket Writable\r\n");
00061         break;
00062     case TCPSOCKET_READABLE:
00063       //Can now read dome data...
00064         printf("TCP Socket Readable\r\n");
00065        // Read in any available data into the buffer
00066        char buff[128];
00067        while ( int len = pConnectedSock->recv(buff, 128) ) {
00068        // And send straight back out again
00069            pConnectedSock->send(buff, len);
00070            buff[len]=0; // make terminater
00071            printf("Received&Wrote:%s\r\n",buff);
00072        }
00073        break;
00074     case TCPSOCKET_CONTIMEOUT:
00075         printf("TCP Socket Timeout\r\n");
00076         break;
00077     case TCPSOCKET_CONRST:
00078         printf("TCP Socket CONRST\r\n");
00079         break;
00080     case TCPSOCKET_CONABRT:
00081         printf("TCP Socket CONABRT\r\n");
00082         break;
00083     case TCPSOCKET_ERROR:
00084         printf("TCP Socket Error\r\n");
00085         break;
00086     case TCPSOCKET_DISCONNECTED:
00087     //Close socket...
00088         printf("TCP Socket Disconnected\r\n");        
00089         pConnectedSock->close();
00090         break;
00091     default:
00092         printf("DEFAULT\r\n"); 
00093       }
00094 }
00095 
00096 
00097 void onListeningTCPSocketEvent(TCPSocketEvent e)
00098 {
00099     switch(e)
00100     {
00101     case TCPSOCKET_ACCEPT:
00102         printf("Listening: TCP Socket Accepted\r\n");
00103         // Accepts connection from client and gets connected socket.   
00104         err=ListeningSock.accept(&client, &pConnectedSock);
00105         if (err) {
00106             printf("onListeningTcpSocketEvent : Could not accept connection.\r\n");
00107             return; //Error in accept, discard connection
00108         }
00109         // Setup the new socket events
00110         pConnectedSock->setOnEvent(&onConnectedTCPSocketEvent);
00111         // We can find out from where the connection is coming by looking at the
00112         // Host parameter of the accept() method
00113         IpAddr clientIp = client.getIp();
00114         printf("Listening: Incoming TCP connection from %d.%d.%d.%d\r\n", 
00115            clientIp[0], clientIp[1], clientIp[2], clientIp[3]);
00116        break;
00117     // the following cases will not happen
00118     case TCPSOCKET_CONNECTED:
00119         printf("Listening: TCP Socket Connected\r\n");
00120         break;
00121     case TCPSOCKET_WRITEABLE:
00122         printf("Listening: TCP Socket Writable\r\n");
00123         break;
00124     case TCPSOCKET_READABLE:
00125         printf("Listening: TCP Socket Readable\r\n");
00126         break;
00127     case TCPSOCKET_CONTIMEOUT:
00128         printf("Listening: TCP Socket Timeout\r\n");
00129         break;
00130     case TCPSOCKET_CONRST:
00131         printf("Listening: TCP Socket CONRST\r\n");
00132         break;
00133     case TCPSOCKET_CONABRT:
00134         printf("Listening: TCP Socket CONABRT\r\n");
00135         break;
00136     case TCPSOCKET_ERROR:
00137         printf("Listening: TCP Socket Error\r\n");
00138         break;
00139     case TCPSOCKET_DISCONNECTED:
00140     //Close socket...
00141         printf("Listening: TCP Socket Disconnected\r\n");        
00142         ListeningSock.close();
00143         break;
00144     default:
00145         printf("DEFAULT\r\n"); 
00146      };
00147 }
00148 
00149 
00150 int main() {
00151   printf("\r\n");
00152   printf("Setting up...\r\n");
00153   EthernetErr ethErr = eth.setup();
00154   if(ethErr)
00155   {
00156     printf("Error %d in setup.\r\n", ethErr);
00157     return -1;
00158   }
00159   printf("Setup OK\r\n");
00160 
00161   IpAddr ip = eth.getIp();
00162   printf("mbed IP Address is %d.%d.%d.%d\r\n", ip[0], ip[1], ip[2], ip[3]);
00163 
00164   
00165   // Set the callbacks for Listening
00166   ListeningSock.setOnEvent(&onListeningTCPSocketEvent); 
00167   
00168   // bind and listen on TCP
00169   err=ListeningSock.bind(Host(IpAddr(), TCP_LISTENING_PORT));
00170   printf("Binding..\r\n");
00171   if(err)
00172   {
00173    //Deal with that error...
00174     printf("Binding Error\n");
00175   }
00176    err=ListeningSock.listen(); // Starts listening
00177    printf("Listening...\r\n");
00178    if(err)
00179    {
00180     printf("Listening Error\r\n");
00181    }
00182  
00183   Timer tmr;
00184   tmr.start();
00185 
00186   while(true)
00187   {
00188     Net::poll();
00189     if(tmr.read() > 0.2) // sec
00190     {
00191       led4=!led4; //Show that we are alive
00192       tmr.reset();
00193     }
00194   }  
00195 }

In the onConnectedTCPSocketEvent, there is an example of how to receive data and echo it back out.

29 Jun 2011

I have use the above code and try to send data > 1608 bytes but cannot success with EthernetNetIf.h lib since some post in http://mbed.org/handbook/Ethernet mention about #define TCP_MSS 536 and in lwipopts.h also said TCP_SND_BUF 3*TCP_MSS =1608. I used wireshark to capture and it showed MSS is 536 and 3 fragment could be send out but the 4th and later fragment was gone.

Q: How can I implement above example code with EhternetNetIf.h lib to send tcp data > 1608 bytes ?

14 Mar 2012

Hi,

I'm trying to send sensor data at 800 packets/s (PPS) using a JSON string over a TCPSocket connection over ethernet.

I used the recommended code example to base my code on.

The JSON packets are about 140 bytes long. I CAN get this to work at 20 PPS but at say 30 PPS or above I see length mismatches, i.e. the line "int slen = pConnectedSock->send( json_str, strlen(json_str) );"

I assume the connection has failed and I then have to await the next writable event before I re-start sending?

So I get bursts of good data then chuncks missing with some garbled packets?

I wish I could find some documentation on this API or TCPSocket method.

Cheers,

Zera

20 Mar 2012

This code by Michael Wei uses TCP raw LwIP API.

http://mbed.org/users/no2chem/programs/EthernetTester/6095m/docs/main_8cpp_source.html

The LwIP API is documented well enough at:

http://lwip.wikia.com/wiki/Raw/TCP

I found this to be the fastest and most reliable way to run TCP. My packets are 300 to 350 bytes long, and I only need to deal with 50 packets/s, but it is reliable. I believe it takes about 8ms to deal with each packet, including some printf debug.

22 Mar 2012

Hi Rod,

Thanks for the post. Oddly I did stumble over that library a while ago, I'll give it a try. At least the documentation seems more complete.

Cheers,

Zera