TCP Newbie Basic Question ... again

I have my TCP client working and sending sending sensor data as json packets to a TCP Server I coded with VB,NET. I noticed one small odd thing, that I am trying to understand and its probably a very basic lack of knowledge on my part how TCP sockets stay alive. The code below is public and looks like so many other minimal TCP clients. My question is in void Setup() where the TCP_Client is first connected. I have tried this on different Arduino Wifi boards, different routers, different PC’s, all the same. The initial “Hello” never is made and only the reconnection “Hello again” is the first TCP data sent and received. It would never be noticeable because the public sample code use “Hello” in both the initial void Setup() as well in the reconnection in void Loop(). Hey, it all works in the end but I am curious why and if you can replicate the same behavior.

/*
 * Created by ArduinoGetStarted.com
 *
 * This example code is in the public domain
 *
 * Tutorial page: https://arduinogetstarted.com/tutorials/arduino-tcp-client
 */

#include <WiFiS3.h>
#include "arduino_secrets.h"

const char* WIFI_SSID = SECRET_SSID;            // my network SSID
const char* WIFI_PASSWORD = SECRET_PASS;        // my network password
const char* TCP_SERVER_ADDR = "192.168.1.2";  // CHANGE TO TCP SERVER'S IP ADDRESS
const int TCP_SERVER_PORT = 1470;

WiFiClient TCP_client;

void setup() {

  Serial.begin(115200);
  Serial.println("Arduino: TCP CLIENT");

  // check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true)
      ;
  }

  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  Serial.print("Attempting to connect to SSID: ");
  Serial.println(WIFI_SSID);
  // attempt to connect to WiFi network:
  while (WiFi.begin(WIFI_SSID, WIFI_PASSWORD) != WL_CONNECTED) {
    delay(10000);  // wait 10 seconds for connection:
  }

  Serial.print("Connected to WiFi ");
  Serial.println(WIFI_SSID);

  // connect to TCP server
  if (TCP_client.connect(TCP_SERVER_ADDR, TCP_SERVER_PORT)) {
    Serial.println("Connected to TCP server");
    TCP_client.write("Hello!");  // send to TCP Server
    TCP_client.flush();
  } else {
    Serial.println("First time connection to TCP server FAILED!!");
  }
}

void loop() {

  if (!TCP_client.connected()) {
    Serial.println("Connection is disconnected");
    TCP_client.stop();

    // reconnect to TCP server
    if (TCP_client.connect(TCP_SERVER_ADDR, TCP_SERVER_PORT)) {
      Serial.println("Reconnected to TCP server");
      TCP_client.write("Hello Again!");  // send to TCP Server
      TCP_client.flush();
    } else {
      Serial.println("Failed to reconnect to TCP server");
      delay(1000);
    }
  }
  // Other Loop code goes below
}

To exclude any potential problems with your custom server, have you tried this with the universal ncat tool? (https://nmap.org/download#windows)

You can start it with listening on port 1470 verbosely with

ncat -lvp 1470

What's the output if you run your Arduino against that?

Does this also mean you see “Connected to TCP server” in the serial monitor??

When you check the result of your client.write() does it equal the string len??

I do kind of remember something strange on first connects but as I also always auto reconnect never bothered me so much..

I would also advise using a state machine in the loop for not only your client but the wifi as well..

example of such..

good luck.. ~q

Serial.begin(115200);
delay(3000);
  Serial.println("Arduino: TCP CLIENT")

thinking some more on this..

you’re probably seeing the affect of the nagle algo that's on by default..

Had to use client.setNoDelay(true); to turn it off..

good luck.. ~q

Instead of my VS2022 VB.NET TCP server I used ezTerm with same results. Here is the serial output on the Arduino R4 Wifi:

20:37:52.779 -> Arduino: TCP CLIENT
20:37:52.814 -> Attempting to connect to SSID: FiOS-JOS
20:37:52.908 -> Connected to WiFi FiOS-JOS
20:38:02.888 -> First time connect to TCP server FAILED!!
20:38:02.921 -> Connection is disconnected
20:38:02.921 -> Reconnected to TCP server

It’s after the reconnection that ezTerm receives the first data “Hello again!”.

I’ll try turning Nagles algorithm as suggested and report back

Ooops, get an error compiling that “'class WiFiClient' has no member named 'setNoDelay'“
I’m using the WiFi3.h library. Will check deeper.

my oops, thought you were using esp32, sorry..

there is no setNoDelay for your client but as it’s not connecting probably not the issue..

maybe the wifi is still doing something on the first go around??

~q

The TСP/IP packet lifetime is 5 seconds. I ping the resource three times and then connect. This problem even exists on ESP.

I placed a few seconds delay after connected to WiFi message and before the line:

delay (5000);
if (TCP_client.connect(TCP_SERVER_ADDR, TCP_SERVER_PORT)) 

and now it works fine.

Yes, figuring out what's wrong with the protocol stack isn't for beginners, but you can use a hack and it will work just fine. I launched one project back in 2016, and it's been running nonstop to this day, with 9 years of uptime.

Your WiFi initialisation looks odd. Why not do it like this in setup()? This is what I do on ESP32.

    WiFi.begin(ssid, password);
    int i = 0;
    while (WiFi.status() != WL_CONNECTED) 
    {
      if (i++ > 0)
      {
        Serial.println("Still connecting ...");
      }
      delay(500);
    }
    Serial.println("WiFi connected.");

I don’t see any functional difference between your code and:

// check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true)
      ;
  }

Serial.print("Connected to WiFi ");

There clearly is something running in the background after the WiFi library code says its connected, that is not yet ready to proceed to open the TCP socket. On my system, the minimal delay required after WiFi connects and for TCP to connect first time (as the code above is written) requires about 50-100 msecs inserted delay.

I was talking about this part of your code

  // attempt to connect to WiFi network:
  while (WiFi.begin(WIFI_SSID, WIFI_PASSWORD) != WL_CONNECTED) {
    delay(10000);  // wait 10 seconds for connection:
  }

I see. Sorry I didn’t pick up on that part of the thread. I just looked at your code and the use of WiFi.begin() in a while loop looked strange to me. I’ve never tried / needed to do that. I’ve got 4 working ESP32 projects using the code that I posted. Three of them are ‘always on’ projects in the house.

Yes there must be something going on. I assume the TCP/IP stack has to do some initialisation after it finds out that it’s got a network connection.