TCP server and client between two photons

Here I am trying to let the two photons communicate with each other with one being server and the other one as a client. But I am really confused by the fact that the client just connect to the server and send data three times and then disconnect.
Here are my code: two parts:server and client

tcp-client.ino


SYSTEM_MODE(MANUAL);

TCPClient client;
byte server[] = { 192, 168, 1, 133 }; // to the queen(one as a server photon)  wlan IP

char* c = "1";


void setup()
{
    
        
    pinMode(D7,OUTPUT);
  // Make sure your Serial Terminal app is closed before powering your device
   Serial.begin(9600);
   WiFi.connect();
  // Now open your Serial Terminal, and hit any key to continue!
  while(!Serial.available()) Particle.process();
  
  //connect to local wifi and show the status
    Serial.println("connecting to wifi");
    
    //while(!WiFi.ready());
    Serial.println(WiFi.localIP());
    Serial.println(WiFi.subnetMask());
    Serial.println(WiFi.gatewayIP());
    Serial.println(WiFi.SSID());

  Serial.println("connecting to server");

  if (client.connect(server, 80))
  {
    Serial.println("server connected");
    /*
    client.println("GET /search?q=unicorn HTTP/1.0");
    client.println("Host: www.google.com");
    client.println("Content-Length: 0");
    client.println();
    */
  }
  else
  {
    Serial.println("connection failed");
  }
}

void loop()
{
   Particle.process(); 
   digitalWrite(D7,HIGH);
    
    client.write(c);
    /*
    if(client.available() > 0){
        Serial.println("write successfully");
        Serial.println(client.read());
        client.flush();
        }
  */
/*
  if (!client.connected())
  {
    Serial.println();
    Serial.println();
    Serial.println("reconnecting.");
    //client.stop();
    //for(;;);
    if(client.connect(server,80)){
        Serial.println("connected");
    }
    else
    {
        Serial.println("connection failed");
    }
  }*/
  delay(100);
  digitalWrite(D7,LOW);
  delay(100);
  
  
}

part 2 ============================================

SYSTEM_MODE(MANUAL);

TCPServer server = TCPServer(80);
//TCPClient client;

void setup()
{
    WiFi.connect();
  
  pinMode(D7,OUTPUT);

  // Make sure your Serial Terminal app is closed before powering your device
  Serial.begin(9600);
  // Now open your Serial Terminal, and hit any key to continue!
  //while(!Serial.available()) 
  //Particle.proceshttps://build.particle.io/build/562c90a9bbdd36b4af0023fc#flashs();

  Serial.println(WiFi.localIP());
  Serial.println(WiFi.subnetMask());
  Serial.println(WiFi.gatewayIP());
  Serial.println(WiFi.SSID());
  
  // start listening for clients
  server.begin();
  
}

void loop()
{
    // check for a new client to our server
    TCPClient client = server.available();
    if (client.connected())
    {
        // we got a new client
        // find where the client's remote address
        IPAddress clientIP = client.remoteIP();
        // print the address to Serial
        Serial.println(clientIP);
    }
    
    Particle.process();
    
    digitalWrite(D7,HIGH);
    
    Serial.println(WiFi.localIP());
    Serial.println(WiFi.subnetMask());
    Serial.println(WiFi.gatewayIP());
    Serial.println(WiFi.SSID());
    
    Serial.println(client.connected());
  if (client.connected()) {
    // echo all available bytes back to the client
    while (client.available()) {
        char c = client.read();
      server.write(c);
      Serial.print("message recieved:");
      Serial.println(c);
    }
  } else {
    // if no client is yet connected, check for a new connection
    client = server.available();
  }
  delay(1000);
  digitalWrite(D7,LOW);
  delay(1000);
}

Could it be that you are running out of free sockets, since you don’t seem to free them after usage?
If the connection times out connected() will turn false, but the socket doesn’t get freed - I think.

Could you repair your formatting please :wink:

SYSTEM_MODE(MANUAL);

TCPServer server = TCPServer(80);
//TCPClient client;

void setup()
{
    WiFi.connect();
  
  pinMode(D7,OUTPUT);

  // Make sure your Serial Terminal app is closed before powering your device
  Serial.begin(9600);
  // Now open your Serial Terminal, and hit any key to continue!
  //while(!Serial.available()) 
  //Particle.proceshttps://build.particle.io/build/562c90a9bbdd36b4af0023fc#flashs();

  Serial.println(WiFi.localIP());
  Serial.println(WiFi.subnetMask());
  Serial.println(WiFi.gatewayIP());
  Serial.println(WiFi.SSID());
  
  // start listening for clients
  server.begin();
  
}

void loop()
{
    // check for a new client to our server
    TCPClient client = server.available();
    if (client.connected())
    {
        // we got a new client
        // find where the client's remote address
        IPAddress clientIP = client.remoteIP();
        // print the address to Serial
        Serial.println(clientIP);
    }
    
    Particle.process();
    
    digitalWrite(D7,HIGH);
    
    Serial.println(WiFi.localIP());
    Serial.println(WiFi.subnetMask());
    Serial.println(WiFi.gatewayIP());
    Serial.println(WiFi.SSID());
    
    Serial.println(client.connected());
  if (client.connected()) {
    // echo all available bytes back to the client
    while (client.available()) {
        char c = client.read();
      server.write(c);
      Serial.print("message recieved:");
      Serial.println(c);
    }
  } else {
    // if no client is yet connected, check for a new connection
    client = server.available();
  }
  delay(1000);
  digitalWrite(D7,LOW);
  delay(1000);
}

@moors7: please check this out:

thank you so much, actually I don’t know what the socket means or to be simply what should I do to solve my problem. :flushed: And above is my server.ino

Try client.stop(); and a short delay before reconnecting.

You can imagine a TCP client like a plugbar the has only a limited number of free sockets and when you plug in a device but never take the plug out even after switching the device of you’ll be running out of places to plug in new devices.

1 Like

I don’t see a client.stop() in the TCPserver example too.

Here is the sample code in the particle reference, I don’t understand what the ‘for(;;)’ for.It seems like a endless for loop. Am I right?

and…
here is my latest result:

And I had my client code modified too, like this::

// EXAMPLE USAGE
SYSTEM_MODE(MANUAL);

TCPClient client;
byte server[] = { 192, 168, 1, 133 }; // to the queen(one as a server photon)  wlan IP

char* c = "1";


void setup()
{
    
        
    pinMode(D7,OUTPUT);
  // Make sure your Serial Terminal app is closed before powering your device
   Serial.begin(9600);
   WiFi.connect();
  // Now open your Serial Terminal, and hit any key to continue!
  while(!Serial.available()) Particle.process();
  
  //connect to local wifi and show the status
    Serial.println("connecting to wifi");
    
    //while(!WiFi.ready());
    Serial.println(WiFi.localIP());
    Serial.println(WiFi.subnetMask());
    Serial.println(WiFi.gatewayIP());
    Serial.println(WiFi.SSID());

  Serial.println("connecting to server");

  if (client.connect(server, 80))
  {
    Serial.println("server connected");
    /*
    client.println("GET /search?q=unicorn HTTP/1.0");
    client.println("Host: www.google.com");
    client.println("Content-Length: 0");
    client.println();
    */
  }
  else
  {
    Serial.println("connection failed");
  }
}

void loop()
{
   Particle.process(); 
   digitalWrite(D7,HIGH);
    
    client.write(c);
    
    if(client.available() > 0){
        Serial.println("reading back");
        Serial.println(client.read());
        client.flush();
        }
  

  if (!client.connected())
  {
    Serial.println();
    Serial.println();
    Serial.println("reconnecting.");
    client.stop();
    for(;;);
    if(client.connect(server,80)){
        Serial.println("connected");
    }
    else
    {
        Serial.println("connection failed");
    }
  }
  delay(500);
  digitalWrite(D7,LOW);
  delay(500);
  
  
}

But in the particle reference TCP server code, there is no server.stop() either. I don’t get it.

The server does not stop since it needs to be on duty for whenever a client demands its services, but internally it makes use of a TCPClient which lifecycle it controls.
To know exactly what’s going on inside TCPServer you could look into the open source implementation.

And for your code change I suggested the client.stop() with a short delay but not the for(;;); since this just traps the code in an endless loop (not a very short delay :wink: ).

The examples just show one very simplistic use case (one time communication) but your use case (multiple communication turns) is different, so the code needs to be different.

Thank you, I really appreciate your help! And I modified the server.ino as well and I find out that it seems not probably to initiate TCPClient client every loop,like the code part haven’t been commented before.And here is my latest server code and it is working now. By the way, I will change the For(;:wink: to a shorter delay and check it if it work.

SYSTEM_MODE(MANUAL);

TCPServer server = TCPServer(80);
TCPClient client;

void setup()
{
    WiFi.connect();
  
  pinMode(D7,OUTPUT);

  // Make sure your Serial Terminal app is closed before powering your device
  Serial.begin(9600);
  // Now open your Serial Terminal, and hit any key to continue!
  //while(!Serial.available()) 
  //Particle.proceshttps://build.particle.io/build/562c90a9bbdd36b4af0023fc#flashs();

  Serial.println(WiFi.localIP());
  Serial.println(WiFi.subnetMask());
  Serial.println(WiFi.gatewayIP());
  Serial.println(WiFi.SSID());
  
  // start listening for clients
  server.begin();
  
}

void loop()
{
    // check for a new client to our server
    /*TCPClient client = server.available();
    if (client.connected())
    {
        // we got a new client
        // find where the client's remote address
        IPAddress clientIP = client.remoteIP();
        // print the address to Serial
        Serial.println(clientIP);
    }
    */
    Particle.process();
    
    digitalWrite(D7,HIGH);
    
    Serial.println(WiFi.localIP());
    Serial.println(WiFi.subnetMask());
    Serial.println(WiFi.gatewayIP());
    Serial.println(WiFi.SSID());
    
    Serial.println(client.connected());
  if (client.connected()) {
    // echo all available bytes back to the client
    while (client.available()) {
        char c = client.read();
      server.write(c);
      Serial.print("message recieved:");
      Serial.println(c);
    }
  } else {
    // if no client is yet connected, check for a new connection
    client = server.available();
  }
  delay(1000);
  digitalWrite(D7,LOW);
  delay(1000);
}

Just had another check and in fact client.connect() does implicitly perform a client.stop() so no need to do it there - sorry for the wrong track :blush:

Only if you’d happened to use a non-global client you should issue a client.stop() before your client object would go out of scope because the TCPClient destructor doesn’t do anything.

1 Like

I`ve done my own basic test , This is my TCPclient which is been called once a second on a timer .

 void server_loop()
{
  client.connect(server, port);
    if ( client.connected() == TRUE )
       {
          client.flush();
          cubie_str = "just a test";
          client.print( cubie_str );
          toggle_led();
        }
}

calling this TCPserver :-

    if (client.connected() == TRUE )
        {
            Serial.println("Some as connected");

            IPAddress clientIP = client.remoteIP();
            Serial.println(clientIP);
            Serial.println(WiFi.localIP());
            client.stop();

        }
        else
        {
            client = server.available();
        }
}

and it`s been running for over 8000 seconds now without any problems

MAYBE NOT , a can see client says it`s connected to the server , and the server is getting a incoming connection from the client , BUT the serial say the incoming ip is 0.0.0.0 .

2 Likes

@peter_a and @particle_adam: I cobbled together some simple photon tcp client and server code that appears to work well on 0.4.7, after reading through lots of posts by way smarter folks than I over the past months on this subject. It’s real simple but might be of use to you. It’s at https://github.com/bprobbins/photon-simple-tcpclientserver

I am really grateful for your reply and I will check it out. Thank you so much!

Well, it may be just unnecessary to print out remote IP but I wanna figure it out how it works. And now I want to move a further step to connect two photon as clients. However, I don’t have any clue right now.

yeah, I think it’s what you mention that cause the disconnection in my project. If I create a client object locally, then I may need to destroy the object every loop, right? :smiley:
By the way, how could I connect two photon as clients to one photon as a server. To be precise, how could the server tell the different ID between the two clients respectively and response to them seperately?

How does it know which client is connected ? , the remote ip address.
I know what you mean about the example , I had to play with it to work out what was happening, talk about cryptic.

Oh my…, I am working on it right now :grin:

I`m having problem with the :-

    IPAddress clientIP = client.remoteIP();
    Serial.println(clientIP); 

After a while it stops telling me the remotes ip.
BUT it is still connecting and still getting data in and out , so the link is still working.
I will try counting the number the of times client.remoteip works before going to 0.0.0.0