1
\$\begingroup\$

I have a few question regarding mbed OS 5's new TCP API:

Some background:

I will have multiple mbeds linked via Ethernet to a PC. The PC, whose IP address is fixed and known by each mbed, initiates the connections (mbeds effectively acting as servers).

The mbed only needs to handle one socket at a time, and the PC should have no problem reconnecting (thereby opening a socket on the mbed) to the mbed, should the connection fail at any point, or the socket is closed by the PC (i.e. the mbed should happily accept and open a socket if there is no open socket).

Question

My proposed approach would be to call accept() on the listener socket, storing the result in a temporary buffer. If the result is NULL (no socket to be accepted), continue. If result is not NULL (we have a pointer to a new socket), close the current socket, and point it to the address returned by accept. All of this, as well as the send() and recv() calls would occur in a while(true) loop.

By accept() returning a new socket, it is assumed that the host (PC) initiated a new connection due to the previous one (which the mbed has no way of telling is now lost) being lost/closed. Therefore, it should be no problem discarding the current socket and replacing it with the new one

Does this seem like a sensible approach?

EDIT:

I've come up with an example of what I was describing above. Hasn't been tested, but should still convey the idea.

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

// Network interface
EthernetInterface net;

TCPSocket listener;
TCPSocket* client;


// Socket demo
int main()
{

    int remaining;
    int rcount;
    char *p;
    char *buffer = new char[256];
    nsapi_size_or_error_t result;

    net.set_network("192,168,0,101","192,168,0,101","192,168,0,101");
    net.connect();

    listener.open(&net);
    listener.bind(80);

    listener.listen(1);

    client = listener.accept(NULL);
    client->set_timeout(1000);

    while(1) {

        int remaining = 256;
        int rcount = 0;
        p = buffer;

        while (remaining > 0 && 0 < (result = client->recv(buffer, remaining))) {
            p += result;
            rcount += result;
            remaining -= result;
        }

        if (result == 0) { //Peer has shutdown connection
            client->close(); //close socket;

            client = listener.accept(NULL); //block again until new connection comes through
            client->set_timeout(1000);
        }


        if (result == NSAPI_ERROR_TIMEOUT ) { //Assume connection has been lost
            client->close(); //close socket;

            client = listener.accept(NULL); //block again until new connection comes through
            client->set_timeout(1000);

        }






    }


}
\$\endgroup\$
  • \$\begingroup\$ Something like that can work in some circumstances however it is not really compliant with TCP where sockets abandoned and not closed are supposed to sit in close_wait state. Also realize that this is only usable on a protected network as its very open to denial of service attacks. You might do better to find a web server example (make sure it works more than trivially) to base your work on. Also consider that by the time you are doing TCP/IP it's worth carefully considering if an "MCU" approach is really best compared to cheap Linux SoC type of one - each has downsides. \$\endgroup\$ – Chris Stratton Mar 21 at 19:48
  • \$\begingroup\$ @ChrisStratton, the network is not connected to the Internet, so security isn't a problem. Could you elaborate on why it is not really compliant with TCP? How would you handle abandoned (not closed) sockets? \$\endgroup\$ – 19172281 Mar 21 at 19:52
  • \$\begingroup\$ An idea might be to check for NSAPI_ERROR_CONNECTION_LOST when calling recv(), or to set a timeout (the host polls the mbed 10/sec, so that would be one way to determine that a connection is lost). \$\endgroup\$ – 19172281 Mar 21 at 20:05
  • \$\begingroup\$ @ChrisStratton, And check for recv() = 0 to indicate peer has closed the connection, so the local socket can be closed. \$\endgroup\$ – 19172281 Mar 21 at 20:31
  • \$\begingroup\$ @ChrisStratton, please see edit. \$\endgroup\$ – 19172281 Mar 21 at 21:43
0
\$\begingroup\$

Why not use UDP in this case? There won't be any socket opening, you can just listen on a socket on the Mbed board and computers can send data to the port. No problem with abandoning sockets.

Note that we have an example of a multi-threaded HTTP 1.1 webserver here: http-webserver-example if you need some inspiration on building TCP servers on top of Mbed OS.

\$\endgroup\$
  • \$\begingroup\$ Error checking is essential so I’ll need to stick with TCP. Do you have any comments on the code I wrote? Cheers \$\endgroup\$ – 19172281 Mar 22 at 9:43
  • \$\begingroup\$ There are many other ways to do error checking than what's built-in to TCP. If you're on a local network with very little packet loss, have the issue of clients random disappearing, rather use UDP and send an acknowledgement back to the client (also over UDP). \$\endgroup\$ – Jan Jongboom Mar 25 at 9:49
  • \$\begingroup\$ Clients disappearing is unlikely to happen, although I feel I should protect for such cases. The system will operate in a noisy environment so packet list could be high. \$\endgroup\$ – 19172281 Mar 25 at 15:17
  • \$\begingroup\$ Well if it doesn't happen often, just listen for new incoming sockets as you're already doing, and at some point (when the connection is lost) you'll get an event on the sigio handler of the old socket (and NSAPI_ERROR_CONNECTION_LOST when calling recv). Then you can clean up. \$\endgroup\$ – Jan Jongboom Mar 25 at 15:47
  • \$\begingroup\$ So is my example code essentially good to go? How does recv determine that the connection is lost though? I was thinking of just doing that with a timeout, as communication is frequent. \$\endgroup\$ – 19172281 Mar 25 at 16:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.