Receive TCP messages from a cleint and perform some actions related in separate thread

Hi,

using NUCLE-F207ZG with Mbed os 5.15 on keil cloud (Mbed studio constinuously crashing on my W11 PC)…
I would like to receive command from a client, reply to request directly; but perform actions requested in the main Thread (meaning that I’ld like to process TCP client/server in a separate Thread.

Despite my efforst to get it works, It looks like the TCP accept or listen is bloking the entire program : I’m able to receive and respond to TCP client messages, but it looks like I never run the main loop.

Here is the code :

/*
 * Copyright (c) 2006-2020 Arm Limited and affiliates.
 * SPDX-License-Identifier: Apache-2.0
 */
#undef __ARM_FP
//#define MBED_CONF_TARGET_DEFAULT_ADC_VREF 1//quick error resolution
#include "mbed.h" //MbedOS 5.15
#include "NetworkInterface.h"


#define BUFFSIZE 50
    
//#define ROUTER // commented = Static IP uncomented = address assigned by router
#ifndef ROUTER
    #define IP          "192.168.184.11"   //Here place your static IP of Mbed
    #define GATEWAY     "0.0.0.0"
    #define MASK        "255.255.255.0"
#endif
#define PORT            23
 
DigitalOut led1(LED1);
volatile int command = 0;//semaphore
NetworkInterface *net = NetworkInterface::get_default_instance();
TCPSocket server;
TCPSocket* client;
SocketAddress clientAddress;
EventQueue queue;

char   *in_buffer;
char   *out_buffer;
SocketAddress ip;
Thread thread;

void tcpRoutine()
{
    // take care of client request and reply
    if(ip)
        { 
            client = server.accept();
 
            client->getpeername(&clientAddress);
            const char *p_clientAddress = clientAddress.get_ip_address();
            printf("Client connected from IP address: %s\n", p_clientAddress ? p_clientAddress : "None");
            
            bool b = true;
            while (b)
            {
                in_buffer = new char[BUFFSIZE];
                int n = client->recv(in_buffer, BUFFSIZE);
                if (n == 0) {
                    printf("Client disconnected\n");
                    b = false;
                }else{
                    in_buffer[n-2] = '\0';
                    printf("Received message from Client :'%s'\n", in_buffer);
                    out_buffer = new char[BUFFSIZE];
                    n = sprintf(out_buffer,"Echo - %s", in_buffer);
                    //parseCommand(&command);
                    printf("Sending echo to client\n");
                    client->send(out_buffer, n);
                    led1 =! led1;
                    delete []out_buffer;
                }
                delete []in_buffer;
            }
            client->close();
        }
    else
        {
            printf("No IP\n");
            net->disconnect();
            //printf("Program end\n");
        }
}

int main (void)
{
    printf("TCP starting...\n");
    int net_stat;

#ifndef ROUTER
    net->disconnect();
    net_stat = net->set_network((SocketAddress)IP,(SocketAddress)MASK,(SocketAddress)GATEWAY);
    printf("set IP status: %i\n",net_stat);
#endif
    net_stat = net->connect();
    printf("connect status: %i\n",net_stat);
 
     
    net->get_ip_address(&ip);
    const char *p_ip = ip.get_ip_address();
    printf("IP address: %s and Port: %d\n", p_ip ? p_ip : "None" , PORT);
    SocketAddress mask;
    net->get_netmask(&mask);
    const char *p_mask = mask.get_ip_address();
    printf("Netmask: %s\n", p_mask ? p_mask : "None");
    SocketAddress gateway;
    net->get_gateway(&gateway);
    const char *p_gateway = gateway.get_ip_address();
    printf("Gateway: %s\n", p_gateway ? p_gateway : "None");
    
    if(ip)
    {
        server.open(net);
        server.bind(PORT);
        server.set_blocking(false);
        //server.set_timeout(15);
        server.sigio(queue.event(tcpRoutine));
        //server.sigio(tcpRoutine);
        server.listen(5);
        printf("Server bound and listening\n");
        queue.dispatch_forever();
    }

    while (1)
    {
        led1 = !led1;
        printf("we are in the main loop...\r\n");
        //wait_us(1000);
        //ThisThread::sleep_for(10);
        // main application code here
        //switch(command)//
        //...
        //thread.start(tcpRoutine);
    }
    
}

Thanks in advance for any guidance

Hello,

hmm, it looks like my example.
I believe, your code never reach main loop because of this line

queue.dispatch_forever();

Try to cut out it, but because you need it place the code below somewhere at start of main.

thread.start(callback(&queue, &EventQueue::dispatch_forever));

BR, Jan

Thanks for ypur quick reply. That is a customized version of your code.
Works well with Thread.start… placed before the while loop.

Additional question : I’ld like to receive command from client, send directly a reply and delay the execuion in the main loop. Is this the best way to proceed ?
I probably have to stop the tcpRoutine’s Thread while reading the share ressource (command) in the main while loop.

Thanks

Great!

I believe there is few ways how to do same thing, however, It depends on your requirements.

BR,Jan