9 years, 1 month ago.

EthernetInterface hangs

I have two FRDM-K64F boards talking to each other using TCP. One is a server, and one is a client. The code is based on the testbench code found in the link: http://developer.mbed.org/users/emilmont/notebook/networking-libraries-benchmark/

The client connects and disconnects from the server many times to test the data throughput and ability to connect/disconnect. Sometimes the server hangs on line 55. It is stuck waiting for something and I'm not sure what. So I wrote a client in python so I could test the server that way. When using the python client, the server has only frozen once. I've had the python run probably 50k test cycles (connect, transmit/receive, disconnect) and it only froze once. The c++ client on the FRDM board freezes about 1 in 100 test cycles and it always freezes on line 55.

Does anyone have any idea why this would be freezing for the FRDM client but not the python client? I've tried inserting time delays at different points to slow down either the server or client but that doesn't seem to help. I thought that maybe the FRDM client runs faster than my laptop and that was causing the issue.

I published both the server and client code and they can be found at the following links:

http://developer.mbed.org/users/timmey9/code/Test_Tcp_Client/

http://developer.mbed.org/users/timmey9/code/Test_Tcp_Server/

Note: The client code has a switch statement for trying different things and debugging. The actual test is under case 'L'.

TCP Server

#include "mbed.h"
#include "EthernetInterface.h"

#define ECHO_SERVER_PORT   54321

#define IP "169.254.225.206"
#define GATEWAY "169.254.225.1"
#define MASK "255.255.0.0"

#define LEN 18980
uint16_t sample_array0[LEN];

DigitalOut led_red(LED_RED);
DigitalOut led_green(LED_GREEN);
DigitalOut led_blue(LED_BLUE);

Serial pc(USBTX,USBRX);

int main (void) {
    for(int i = 0; i < LEN; i++) sample_array0[i] = ((0x0031<<8) | 0x0032);
    sample_array0[0] = ('S'<<8)|'S';
    sample_array0[LEN-1] = ('F'<<8) | 'F';
    pc.baud(230400);
    pc.printf("Starting test server\r\n");
    
    EthernetInterface eth;
    eth.init(IP, MASK, GATEWAY);
    eth.connect();
    pc.printf("IP Address is %s\r\n", eth.getIPAddress());
    
    TCPSocketServer server;
    server.bind(ECHO_SERVER_PORT);
    server.listen();
    
    led_blue = 1;
    led_green = 1;
    led_red = 1;
    
    while (true) {
        //pc.printf("\r\nWait for new connection...\r\n");
        
        
        TCPSocketConnection client;
        server.accept(client);
        client.set_blocking(true, 5000);
            
        //pc.printf("Connection from: %s\r\n", client.get_address());
        char buffer[1460]; // size of IP payload
        while (true) {
            int n = client.receive(buffer, sizeof(buffer));
            if (n <= 0) break;
            pc.printf("Rec: %i: ",n);
            

            n = client.send_all((char *)sample_array0, LEN*2);
            
            if (n <= 0) {led_blue = 0; break;}
            pc.printf("Sent %i: ",n);
        }
        
        client.close();
        pc.printf("\r\n");
    }
}

TCP Client

#include "mbed.h"
#include "EthernetInterface.h"

#define PORT   54321

#define LEN_PACKET 1460

#define IP         "169.254.225.220"
#define GATEWAY    "169.254.225.1"
#define MASK       "255.255.0.0"
#define DES_ADDR   "169.254.225.206"
#define DES_LAPTOP "169.254.225.210"

#define LEN 18980
uint16_t sample_array0[LEN];

Serial pc(USBTX,USBRX);

int main (void) {
    for(int i = 0; i < LEN; i++) sample_array0[i] = ((0x0031<<8) | 0x0032);
    pc.baud(230400);
    pc.printf("Starting test client\r\n");
    EthernetInterface eth;
    eth.init(IP, MASK, GATEWAY);
    eth.connect();
    pc.printf("IP Address is %s\r\n", eth.getIPAddress());
    
    TCPSocketConnection mallet;
    mallet.set_blocking(false,5000);
    char buffer[LEN_PACKET];
    
    for(int i = 0; i < LEN_PACKET; i++) buffer[i] = i;
    while (true) {
        if(pc.readable() > 0){
            char temp = pc.getc();
            int var = 0;
            switch(temp){
                case 'Q':
                case 'q':
                    var = mallet.connect(DES_LAPTOP,5005);
                    if(var == 0) pc.printf("Connected to laptop successfully\r\n");
                    else if(var == -1) pc.printf("Connecting failed\r\n");
                    break;
                case 'A':
                case 'a':
                    var = mallet.connect(DES_ADDR,PORT);
                    if(var == 0) pc.printf("Connected to FRDM server successfully\r\n");
                    else if(var == -1) pc.printf("Connecting failed\r\n");
                    break;
                case 'S':
                case 's':
                    var = mallet.send(buffer,LEN_PACKET);
                    pc.printf("Sent %i bytes\r\n",var);
                    break;
                case 'D':
                case 'd':
                    var = mallet.receive_all((char *)sample_array0,LEN*2);
                    pc.printf("Received %i bytes\r\n",var);
                    break;
                case 'F':
                case 'f':
                    var = mallet.close();
                    if(var == 0) pc.printf("Connection closed\r\n");
                    else pc.printf("Error while closing connection\r\n");
                    break;
                case 'Z':
                case 'z':
                    pc.printf("Status: ");
                    if(mallet.is_connected()) pc.printf("Connected\r\n");
                    else pc.printf("Not connected\r\n");
                    break;
                case 'R':
                case 'r':
                    // open connection
                    var = mallet.connect(DES_ADDR,PORT);
                    if(var == 0) pc.printf("Connected successfully\r\n");
                    else if(var == -1) pc.printf("Connection already open\r\n");
                    
                    // send data
                    var = mallet.send(buffer,LEN_PACKET);
                    pc.printf("Sent %i bytes\r\n",var);
                    
                    // receive data
                    var = mallet.receive_all((char *)sample_array0,LEN*2);
                    pc.printf("Received %i bytes\r\n",var);
                    
                    // closed connection
                    var = mallet.close();
                    if(var == 0) pc.printf("Connection closed\r\n\n");
                    else pc.printf("Error while closing connection\r\n\n");
                    break;
                case 'L':
                case 'l':
                    for(int i = 0; i < 1000; i++){
                        //wait_ms(100);
                        pc.printf("%3i: ",i);
                        
                        // open connection
                        var = mallet.connect(DES_ADDR,PORT);
                        if(var == -1) {i = 50; break;}
                        
                        // send data
                        var = mallet.send(buffer,LEN_PACKET);
                        pc.printf("Sent %i: ",var);
                        if(var == -1) {i = 50; break;}
                        
                        // receive data
                        var = mallet.receive_all((char *)sample_array0,LEN*2);
                        pc.printf("Rec %i: ",var);
                        if(var == -1) {i = 50; break;}
                        
                        // closed connection
                        var = mallet.close();
                        if(var == -1) {i = 50; break;}
                        pc.printf("\r\n");
                        
                    }
                    break;
            }
        }
    }
}

Python TCP client

import socket
import random, string
from time import time
from time import sleep
MAX_SEGMENT_SIZE = 1460 
ECHO_SERVER_ADDRESS = "169.254.225.206"
ECHO_SERVER_PORT = 54321

N_PACKETS = 40*3*NUM_MALLETS/2
LEN_PACKET = 1460
N_SAMPLES = LEN_PACKET*N_PACKETS # approximately 29200 uint16 * 3 instruments

PACKET = ''.join(random.choice(string.ascii_uppercase+string.digits) for _ in range(LEN_PACKET))

UPDATE_STEP = (N_PACKETS/10)
bytes = []
times = []
CNT = 3000
total = time()
for x in range(CNT):
    #connect
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ECHO_SERVER_ADDRESS, ECHO_SERVER_PORT))
    
    #send data
    start = time()
    s.sendall(PACKET)
    
    #receive response
    data = s.recv(18980*2)
    
    length = len(data)
    t = time() - start
    bytes.append(length)
    times.append(t)
    
    #close
    s.close()
    
    if((x%100) == 0):
       print "{0:3.0f}% ".format(float(x)/float(CNT)*100)
total = time()-total
print "100%\n"


avg_bytes = reduce(lambda x, y: x + y,bytes)/float(len(bytes))
avg_time = reduce(lambda x, y: x + y,times)/float(len(times))
print "Average bytes:        {0:f} bytes".format(avg_bytes)
print "Average time:         {0:f} s".format(avg_time)
print "Average receive rate: {0:.3f} MB/s".format(avg_bytes/avg_time/1024/1024)
print "Average receive rate: {0:.3f} Mb/s".format(avg_bytes*8/avg_time/1024/1024)
print "Overall receive rate: {0:.3f} MB/s".format(avg_bytes*CNT/total/1024/1024)

Hi Joey,

Did you ever find the issue with this? I'd be willing to help investigate.

Thanks, Brian

posted by Brian Daniels 19 May 2015

Not really. I just figured out how to avoid it using trial and error. It is probably worth investigating for future reference, but I believe I have sufficiently dodged the problem for my application.

posted by Joey McElderry 21 May 2015

Hi Joey, I've replicated the issue that you described for the two mBed's talking over Ethernet.

According to the prints, it looks like it's getting frozen on the server side. The client has a "Sent message" without a receive, and the server has a "receive" message without a sent message. I'll keep investigating

posted by Brian Daniels 21 May 2015
Be the first to answer this question.