TCP Server responding very slowly

01 Jul 2011

I slightly modified the TCPServer program to respond to calls from a client that calculates the round-trip time and the number of messages echoed per second. I only get something like 4 messages per second, independetly on the message length. The times to complete the onLinkSocketEvent callback are around 7 us to send and 14 us to receive.

Here's the TCPServer ###############

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"

EthernetNetIf eth(        // Brings up the device with static IP address and domain name.
                IpAddr(192,168,1,177),   // IPv4 address
                IpAddr(255,255,255,0),   // netmask
                IpAddr(192,168,1,1),     // default gateway
                IpAddr(192,168,1,1));    // dns server
DigitalOut led1(LED1);


TCPSocket tcp;  //The listening port where requests are queued
TCPSocket* link; //The port where accepted requests can communicate

Host local(IpAddr(), 10003); //mbed IP
Host client;

TCPSocketErr accErr;
Timer TimG;
Ticker To;
int Nf=0;
int readable=0;
int writeable=0;
int accepted=0;
int connected=0;
char ack = 0xe;



void onLinkSocketEvent(TCPSocketEvent e)
{

char buff[128];

Timer Tim;
Tim.reset();
Tim.start();
 
// printf("link Callback evt %d\n",e );
 switch(e)
   {
    case TCPSOCKET_CONNECTED:
            printf("TCP Socket Connected\r\n");
            connected =1;
        break;
    case TCPSOCKET_WRITEABLE:
      //Can now write some data...
        //printf("TCP Socket Writable\r\n");
        printf("w ");
        writeable=1;
        break;
    case TCPSOCKET_READABLE:
        readable=1;
      //Can now read dome data...
        //printf("TCP Socket Readable\r\n");
       // Read in any available data into the buffer
             while ( int len = link->recv(buff, 128) ) {            
       // And send straight back out again
       link->send(&ack, 1);        
       }
      readable=0;
       break;
    case TCPSOCKET_CONTIMEOUT:
        //printf("TCP Socket Timeout\r\n");
        break;
    case TCPSOCKET_CONRST:
        //printf("TCP Socket CONRST\r\n");
        break;
    case TCPSOCKET_CONABRT:
       // printf("TCP Socket CONABRT\r\n");
        break;
    case TCPSOCKET_ERROR:
      //  printf("TCP Socket Error\r\n");
        break;
    case TCPSOCKET_DISCONNECTED:
    //Close socket...
        printf("TCP Socket Disconnected\r\n");        
        link->close();
        connected =0;
        break;
    default:
        printf("DEFAULT\r\n"); 
      }
 readable=0;  
 writeable=0;   
   Tim.stop();
      

  TimG.stop();
  printf("Time Step us %d Nf=%d\n", Tim.read_us(), Nf);
  TimG.reset();
  Tim.reset();  
}

void onTCPSocketEvent(TCPSocketEvent e)
{
    Timer Tim;  
    TimG.start();
    Tim.start();
    switch(e) {
        case TCPSOCKET_CONNECTED:
            printf("Connected\n");
        break;
        
        case TCPSOCKET_ACCEPT: {
            accErr = tcp.accept(&client,&link);
            switch(accErr) {
                case TCPSOCKET_SETUP:   printf("Err:Setup\n");      break;  //TCPSocket not properly configured.
                case TCPSOCKET_TIMEOUT: printf("Err:Timeout\n");    break;  //Connection timed out.
                case TCPSOCKET_IF:      printf("Err:Interface\n");  break;  //Interface has problems, does not exist or is not initialized.
                case TCPSOCKET_MEM:     printf("Err:Memory\n");     break;  //Not enough mem.
                case TCPSOCKET_INUSE:   printf("Err:In use\n");     break;  //Interface / Port is in use.
                case TCPSOCKET_EMPTY:   printf("Err:Empty\n");      break;  //Connections queue is empty.
                case TCPSOCKET_RST:     printf("Err:Reset\n");      break;  //Connection was reset by remote host.
                case TCPSOCKET_OK:      printf("Accepted: ");       break;  //Success. 
            }
            link->setOnEvent(&onLinkSocketEvent);
            IpAddr clientIp = client.getIp();
            accepted=1;
            printf("Incoming TCP connection from %d.%d.%d.%d\r\n", 
            clientIp[0], clientIp[1], clientIp[2], clientIp[3]);
        }
        break;
        
        case TCPSOCKET_READABLE:
            printf("Readable\n");
        break;
        
        case TCPSOCKET_WRITEABLE:
            writeable=1;
            printf("Writeable\n");
        break;
        
        case TCPSOCKET_CONTIMEOUT:
            printf("Timeout\n");
        break;
        
        case TCPSOCKET_CONRST:
            printf("Reset\n");
        break;
        case TCPSOCKET_CONABRT:
            printf("Aborted\n");
        break;
        
        case TCPSOCKET_ERROR:
            printf("Error\n");
        break;
        
        case TCPSOCKET_DISCONNECTED:
            printf("Disconnected\n");
            tcp.close();
           accepted =0;
        break;    
    }
    Tim.stop();
    printf("Accept Callback Timer %d\n", Tim.read_us());
    Tim.reset();
}


void DataFilt()
{
  Nf++; 
}

int main() {
    Timer Tim;
    To.attach(&DataFilt, 0.01);
    //********Basic setup********
    printf("Welcome to wireFUSE\n");
    printf("Setting up...\n");
    EthernetErr ethErr = eth.setup();
    if(ethErr)
    {
        printf("Error %d in setup.\n", ethErr);
        return -1;
    }
    printf("Setup OK\n");
    //****End of basic setup*****
    tcp.setOnEvent(&onTCPSocketEvent); //Generate method to deal with requests
    
    //Bind to local port
    printf("Init bind..\n");
    TCPSocketErr bindErr = tcp.bind(local);
    switch(bindErr) {
    case TCPSOCKET_SETUP:   printf("Err:Setup\n");      break;  //TCPSocket not properly configured.
    case TCPSOCKET_TIMEOUT: printf("Err:Timeout\n");    break;  //Connection timed out.
    case TCPSOCKET_IF:      printf("Err:Interface\n");  break;  //Interface has problems, does not exist or is not initialized.
    case TCPSOCKET_MEM:     printf("Err:Memory\n");     break;  //Not enough mem.
    case TCPSOCKET_INUSE:   printf("Err:In use\n");     break;  //Interface / Port is in use.
    case TCPSOCKET_EMPTY:   printf("Err:Empty\n");      break;  //Connections queue is empty.
    case TCPSOCKET_RST:     printf("Err:Reset\n");      break;  //Connection was reset by remote host.
    case TCPSOCKET_OK:      printf("Bound to port\n");  break;  //Success. 
    }
            
    //Listen to local port
    printf("Init listen..\n");
    TCPSocketErr listenErr = tcp.listen();
    switch(listenErr) {
    case TCPSOCKET_SETUP:   printf("Err:Setup\n");      break;  //TCPSocket not properly configured.
    case TCPSOCKET_TIMEOUT: printf("Err:Timeout\n");    break;  //Connection timed out.
    case TCPSOCKET_IF:      printf("Err:Interface\n");  break;  //Interface has problems, does not exist or is not initialized.
    case TCPSOCKET_MEM:     printf("Err:Memory\n");     break;  //Not enough mem.
    case TCPSOCKET_INUSE:   printf("Err:In use\n");     break;  //Interface / Port is in use.
    case TCPSOCKET_EMPTY:   printf("Err:Empty\n");      break;  //Connections queue is empty.
    case TCPSOCKET_RST:     printf("Err:Reset\n");      break;  //Connection was reset by remote host.
    case TCPSOCKET_OK:      printf("Listening\n");      break;  //Success. 
    }
   // Timer tmr;
    //tmr.start();
    if(accepted)
    {
      Net::poll();     
    }
    while(!readable)
    {
      Net::poll();     
    }
 
}

#########3 This is the result of the Sender/receiver

./testTCPSender 192.168.1.177 10 10 10003
 out 0
min 109878       max 250011
sum 2359730.000000 sum2 24743399424.000000
 Avg. 235973.000000      Sigma nan
 Delta T = 2359747 (usec)
 4.237742 messages/sec

######### Here is the packet dump on the sender/receiver

tcpdump src 192.168.1.177 or dst 192.168.1.177
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes
12:15:09.553268 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: S 262914439:262914439(0) win 5840 <mss 1460,sackOK,timestamp 1287352803 0,nop,wscale 7>
12:15:09.553345 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: S 11490:11490(0) ack 262914440 win 2144 <mss 536>
12:15:09.553359 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: . ack 1 win 5840
12:15:09.553576 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: P 1:11(10) ack 1 win 5840
12:15:09.663160 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: P 1:2(1) ack 11 win 2134
12:15:09.663340 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: . ack 2 win 5840
12:15:09.663456 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: P 11:21(10) ack 2 win 5840
12:15:09.913172 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: P 2:3(1) ack 21 win 2124
12:15:09.913265 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: P 21:31(10) ack 3 win 5840
12:15:10.163182 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: P 3:4(1) ack 31 win 2114
12:15:10.163274 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: P 31:41(10) ack 4 win 5840
12:15:10.413188 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: P 4:5(1) ack 41 win 2104
12:15:10.413276 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: P 41:51(10) ack 5 win 5840
12:15:10.663200 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: P 5:6(1) ack 51 win 2094
12:15:10.663287 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: P 51:61(10) ack 6 win 5840
12:15:10.913207 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: P 6:7(1) ack 61 win 2084
12:15:10.913300 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: P 61:71(10) ack 7 win 5840
12:15:11.163214 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: P 7:8(1) ack 71 win 2074
12:15:11.163307 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: P 71:81(10) ack 8 win 5840
12:15:11.413222 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: P 8:9(1) ack 81 win 2064
12:15:11.413314 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: P 81:91(10) ack 9 win 5840
12:15:11.663232 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: P 9:10(1) ack 91 win 2054
12:15:11.663324 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: P 91:101(10) ack 10 win 5840
12:15:11.913234 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: P 10:11(1) ack 101 win 2044
12:15:11.913737 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: F 101:101(0) ack 11 win 5840
12:15:11.913853 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: . ack 102 win 2043
12:15:11.966174 IP 192.168.1.177.10003 > lxvirgo5.na.infn.it.36194: F 11:11(0) ack 102 win 2043
12:15:11.966196 IP lxvirgo5.na.infn.it.36194 > 192.168.1.177.10003: . ack 12 win 5840

####