TCPsocket: can't figure it out

Hi everyone,

I’m trying to build an application with TCPsocket.
My mbed device should be configured with a static ip.
I want to send a TCP package to an ip i can choose with port 4000.
Also i should be able to receive a TCP package from another device on the same port.
I’ve been struggling with this for some time but i can’t figure it out.
This is the code i have until now but i don’t know what to do next.
// Define Network interface
EthernetInterface net;

// Bring up the ethernet interface
pc.printf("Start Ethernet Connection\n");
net.set_network(IP_Adress,GATEWAY,NETMASK); //My IP or IP i want to connect to?
net.connect();

// Show the network address
SocketAddress a;

// Open a socket on the network interface, and create a TCP connection to mbed.org
TCPSocket socket;
socket.open(&net);

 a.set_port(4000); //socket number 4000 was eerst 80
socket.connect(a); 

What about the bind/listen and accept function for the TCP socket?
Can somebody help me to get this to work?

Hello,

TCPsocket contains methods for TCP client servise and also for TCP server. Methods what you mentioned are for TCPserver.
TCPSocketServer socket section.

If your socket is already connected then you can try to send or recv some data. Also is good to check results what these methods will return - Error Codes

BR, Jan

Thank you for your reply.
How can i connect a socket? Where should i insert the IP address i want to send a TCP package?

You need to fill SocketAddress according to one of constructor version. Then pass it to the connect() method how you have it above.

   SocketAddress addr("YOUR_DESTINATION_IP", YOUR_DESTINATION_PORT_NUMER);
//or
   addr.set_ip_address("YOUR_DESTINATION_IP")
   addr.set_port(YOUR_DESTINATION_PORT_NUMER);
//then
   socket.connect(addr); 

BR, Jan

Dear Jan,

Thank you for your feedback.
I have manages to setup a socket.
// Define Network interface
EthernetInterface net;

// Bring up the ethernet interface
pc.printf("Start Ethernet Connection\n");
net.set_network(IP_Adress,GATEWAY,NETMASK); //setup the ethernet interface
net.connect(); //activate ethernet interface

// Show the network address
SocketAddress client;

// Open a socket on the network interface, and create a TCP connection to mbed.org
TCPSocket socket;
socket.open(&net);
client.set_ip_address("192.168.0.120");
client.set_port(4000); //socket number 4000 was eerst 80
socket.connect(client);

Do i have to bind this socket?
I also want to receive TCP packages. So i need to make a second socket to receive data?

Nope, bind() method and second socket are necessary only for TCPserver. So if you want to be a Client that is OK.

BR, Jan

Dear Jan,

I want to send and receive from the same device. I want to listen all the time for incoming packages. If i push a button i want to start sending data. So i guess i would need both client and server capabilities?

TCP Server - it only wait for a client. How is a client connected then is the communication bidirectional.
TCP Client - it can connect to a server. How it is connected to a server then is the communication bidirectional.

If you want to try TCP Server just try this example → TCP_EchoServer

BR, Jan

Dear Jan,

Communication is indeed bidirectional. But not from the same device. I receive from IPx and send a reply to IPy. So for this i need 2 sockets right?

Sorry for late reply.
Probably more than only 2.
For example, when a TCPclient device will send some data and your board will receive the data as TCPserver and then re-send some data to different TCPserver device, then you need 3 sockets

  1. socket as TCPserver for accept of incoming client connection
  2. socket for accepted client and its processing (recv data)
  3. socket for local client what will re-sending received data to another server

BR, Jan

Dear Jan,

Thank you for your feedback.
So i have tried to make some code to get this to work.
At all times i should be able to start sending with the push of a button.
Also the server socket should be listening all the time for incoming messages.
Could you have a look at my code? Should this work?

#include "mbed.h"
#include "Arrays.h" //Array file

#include "C12832.h" // Display lib
#include "LM75B.h"  //Temp sensor lib
//#include "MyFunctions.h"
#include "EthernetInterface.h"  //TCP/IP lib

#define DEBUG

//Serial Port init
Serial pc(USBTX, USBRX);

//define network parameters
#define IP_Adress  "192.168.1.106"
#define GATEWAY "192.168.0.1"
#define NETMASK "255.255.255.0"

/*
// Max X value of LCD screen
#define MAX_X 124
// Max Y value of LCD screen
#define MAX_Y 28
*/

//Temp sensor init
LM75B sensor(D14,D15);

// Joystick Pins
DigitalIn JoystickUp(A2);
DigitalIn JoystickDown(A3);
DigitalIn JoystickLeft(A4);
DigitalIn JoystickRight(A5);
DigitalIn JoystickPush(D4);

// Potentiometer Pins
AnalogIn pot1 (A0);

// RGB LED pin
PwmOut red (D5);

//Define pins for display
C12832 lcd(D11, D13, D12, D7, D10);

//Speaker pin
PwmOut spkr(D6);

int main()
{
    char rbuffer[256];
    char sbuffer[256];
    char IPreceiver[20];
    int rcount;
    // Define Network interface
    EthernetInterface net;
    net.set_network(IP_Adress,GATEWAY,NETMASK); //setup the ethernet interface
    net.connect(); //activate ethernet interface

#ifdef DEBUG
    pc.printf("Start Ethernet Connection\n");
#endif

    TCPSocket server;
    TCPSocket *serverReceive;
    TCPSocket client;

    if(server.open(&net) < 0) { //open network socket
#ifdef DEBUG
        pc.printf("Could not open server socket\n");
#endif
    }

    if(server.bind(4000) < 0) {
#ifdef DEBUG
        pc.printf("Could not bind server socket\n");
#endif
    }

    if(server.listen(1) < 0) {
#ifdef DEBUG
        pc.printf("Could not put server socket in listening mode\n");
#endif
    }

    while(1) {  //main while loop

        serverReceive = server.accept();
        rcount = serverReceive->recv(rbuffer,256);

        if(rcount != 0) {
            //We have received some data--> do something with it!
        }


        if(JoystickPush) {
            //Button is pushed--> start sending data as a first node

            if (client.open(&net) < 0) {
#ifdef DEBUG
                pc.printf("Could not open client socket\n");
#endif
            }
            if(client.connect(IPreceiver,4000) < 0) {
#ifdef DEBUG
                pc.printf("Could not connect client socket\n");
#endif
            }
            if(client.send(sbuffer, 256)) {
#ifdef DEBUG
                pc.printf("Could not send to client\n");
#endif
            }
            client.close(); //close socket after message sent
        }
    }

}

Hello,

  • It is also necessary to close the serverReceive socket at the end of loop, it will prevent memory leak. Or if your connection will remain then you will need to manage without another accept.
  • It is good to check rcount is 0 that tell you client disconnected.
  • I am not sure about JoystickPush because Sockets are in blocking mode in default. So the method recv(...) will block the rest of code until new message will coming, and you will must hold button for the same time.

TIP: you can use printf without pc object for debugging via console and instead of these many macros you can use it via this. Just place the code below instead of printf.

#define DEBUG 1 
debug_if(DEBUG, "Mbed OS version %d.%d.%d\n\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);

BR, Jan

Dear Jan,

I see thank you for your feedback. So the program will stop at the recv() function until it receives a packet? So how should i arrange the code so it will listen all the time if it receives something or if i push the button it will send a package over tcp? Could i implement and if statement when the server.listen statement receives a package? So i can open the serverReceive socket inside this if statement? Or should i use threads to solve this issue?

Yes, exactly.
There are many variant how you can work around this but it depends about details of your requirements.
As start you can use rise/fall interrupt and set a boolean flag to true, then processed it in the loop and set it back to false.
Also you can use threads and run these connections separately but maybe it will be better to use EventQueue. Then you can place the client to a separate function and call it via EQ after a message received or from button press event.

BR, Jan