Arduino R4 Wifi / VS2022 TCP Client/Server

I want to pass sensor data to my PC and do some analytics and graphic display. I am stuck at the basic TCP Server/Client level. I know I can do this via UDP, HTTP, but thought the code for TCP should be the easiest. The Arduino sketch successfully connects to my local WiFi but fails to connect to the VS 2022 TCP server. The VS 2022 server is 'listening' on the correct address and port when I run a Command prompt netstat /a.

Any advice very much appreciated:

The Arduino sketch is:

#include <WiFiS3.h>

#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;  // your network SSID (name)
char pass[] = SECRET_PASS;  // your network password (use for WPA, or use as key for WEP)

const char* TCP_SERVER_ADDR = "127,0,0,1";   //also tried "127.0.0.1"
const int TCP_SERVER_PORT = 64555;
WiFiClient TCP_client;

int status = WL_IDLE_STATUS;  // the WiFi radio's status

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ;  // wait for serial port to connect. Needed for native USB port only
  }

  // 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");
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(ssid, pass);

    // wait 5 seconds for connection:
    delay(5000);
  }

  // you're connected now, so print out the data:
  Serial.print("You're connected to the network");
  printCurrentNet();
  printWifiData();

  //connect to TCP server
  if (TCP_client.connect(TCP_SERVER_ADDR, TCP_SERVER_PORT)) {
    Serial.println("Connected to TCP server");
    TCP_client.write("Hello!");
    TCP_client.flush();
  } else {
    Serial.println("Failed to connect to TCP server");
  }
}

void loop() {
  // check the network connection once every 10 seconds:
  delay(10000);
  printCurrentNet();
  if (TCP_client.available()) {
    char c = TCP_client.read();
    Serial.print(c);
  }

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

    //reconnect
    if (TCP_client.connect(TCP_SERVER_ADDR, TCP_SERVER_PORT)) {
      Serial.println("Reconnected to TCP Server");
      TCP_client.write("Hello again");
      TCP_client.flush();
    } else {
      Serial.println("Failed to reconnect to TCP server");
      delay(1000);
    }
  }
}

void printWifiData() {
  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");

  Serial.println(ip);

  // print your MAC address:
  byte mac[6];
  WiFi.macAddress(mac);
  Serial.print("MAC address: ");
  printMacAddress(mac);
}

void printCurrentNet() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print the MAC address of the router you're attached to:
  byte bssid[6];
  WiFi.BSSID(bssid);
  Serial.print("BSSID: ");
  printMacAddress(bssid);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.println(rssi);

  // print the encryption type:
  byte encryption = WiFi.encryptionType();
  Serial.print("Encryption Type:");
  Serial.println(encryption, HEX);
  Serial.println();
}

void printMacAddress(byte mac[]) {
  for (int i = 0; i < 6; i++) {
    if (i > 0) {
      Serial.print(":");
    }
    if (mac[i] < 16) {
      Serial.print("0");
    }
    Serial.print(mac[i], HEX);
  }
  Serial.println();
}

The VS 2022 TCP Server code is:

Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading

'use command prompt and type netstat /a to see if port is open

Public Class TCPControl
    Public Event MessageReceived(sender As TCPControl, Data As String)

    ' SERVER CONFIG
    Public ServerIP As IPAddress = IPAddress.Parse("127.0.0.1")


    Public ServerPort As Integer = 64555
    Public Server As TcpListener

    Private CommThread As Thread
    Public IsListening As Boolean = True

    ' CLIENTS
    Private Client As TcpClient
    Private ClientData As StreamReader

    Public Sub New()
        Server = New TcpListener(ServerIP, ServerPort)
        Server.Start()

        CommThread = New Thread(New ThreadStart(AddressOf Listening))
        CommThread.Start()
    End Sub

    Private Sub Listening()
        ' CREATE LISTENER LOOP
        Do Until IsListening = False
            ' ACCEPT INCOMING CONNECTIONS
            If Server.Pending = True Then
                Client = Server.AcceptTcpClient
                ClientData = New StreamReader(Client.GetStream)

            End If

            ' RAISE EVENT FOR INCOMING MESSAGES
            Try
                RaiseEvent MessageReceived(Me, ClientData.ReadLine)
            Catch ex As Exception

            End Try

            ' REDUCE CPU USAGE
            Thread.Sleep(100)
        Loop
    End Sub
End Class

I got rid of the VS2022 TCP server and instead tried with ezTerm configured ats TCPServer with port same as the Arduino sketch - 64555. Still no luck so it seems the problem is with my Arduino sketch. For TCP_SERVER_ADDR, TCP_SERVER_PORT I tried my PC's localhost of 127.0.0.1 as well as the ipaddress of my PC - while keeping port same at 674555. No connection. Any advice appreciated.

I further reduced extraneous code. Here is sketch from public domain for simple Arduino TCP client to an ezTerm TCP client. I cannot get this to work and I removed my firewalls and virus software. I am not sure what the TCPServer address should be. Is it the ip address for my PC running ezTerm? Is it the ezTerm remote default address of 10.0.1.0? I tried different Ports not in use, such as 64555 or ezTerm default of 1470. No success

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

#include <WiFiS3.h>

const char* WIFI_SSID = "FiOS-Guest";          // CHANGE TO YOUR WIFI SSID
const char* WIFI_PASSWORD = "121899021602";       // CHANGE TO YOUR WIFI PASSWORD
const char* TCP_SERVER_ADDR = "127.0.0.1";  // CHANGE TO TCP SERVER'S IP ADDRESS
const int TCP_SERVER_PORT = 1470;

WiFiClient TCP_client;

void setup() {
  Serial.begin(9600);

  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("Failed to connect to TCP server");
  }
}

void loop() {
  // Read data from server and print them to Serial
  if (TCP_client.available()) {
    char c = TCP_client.read();
    Serial.print(c);
  }

  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!");  // send to TCP Server
      TCP_client.flush();
    } else {
      Serial.println("Failed to reconnect to TCP server");
      delay(1000);
    }
  }
}

Maybe simplify your problem. Create the server using 1 sensor and just create a web browser client. Get that code from the examples that come with whatever library you choose to use.
Once that works well, add whatever code is needed to do the analytics and graphics. Now add in more sensors.

127.0.0.1 is not going to work, for neither the client nor server. That is the "local loopback", used to call services on the same "box". (I've never tried running the WiFiServer and WiFiClient on the same Arduino, calling itself. Would that work on R4? Never mind.)

After connecting, print the IP address assigned to the R4 by the router

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

It will likely be either 192.168.something.something or 10.x.y.z; with your subsequent posts, maybe the latter. The PC running the server would have a similar -- but not the same -- address. (If not, they are not on the same subnet, and it won’t work.) You said you've got that already.

Once you have the server's IP address, might as well be explicit in defining it; for example

IPAddress TCP_SERVER_ADDR{ 10, 0, 0, 99 };  // commas

Using brace initialization will catch certain kinds of errors. For example, numbers out of range

Knowing almost nothing about .NET TcpListener, you might have better luck allowing connections from any network interface on the machine, not just the local loopback

TcpListener(IPAddress.Any, ServerPort)

Use the terminal program to try connecting to that server using the PC's IP address.

The ipaddress for ezTerm as a TCPServer is supposed to be the same as the ipaddress of the PC running exTerm. However, when I check with commnad prompt running netstat /a, ezTerm is listening on 0.0.0.0 and the selected port. I have tried several different ports for ezTerm and netstat sees them all as 0.0.0.0. On the Arduino client side, I have tried the ipaddress of the PC (same 192.168.1.xxx) as the Arduino (192.168.1.yyy). But netstat does not show any device listening on whatever port I choose except as 0.0.0.0:"myportnumber". I have tried every permutation without success.

My problem seems to be the Arduino sketch in my initial msg. I ran the VS 2022 TCP Server program and used ezTerm as a TCP client. I chose the server ip as 127.0.0.1:64555 and the ezTerm as a client sending to the same ip:port and had not problems. ezTerm connected to the VS program right away and data was sent and received in both directions. Not clear to me at all why the Arduino sketch cannot use the same target local host ip:port addresses.

Again, 127.0.0.1 means "on this box". You can call services running on various ports on the same box; but the Arduino would be attempting to connect to the port on itself, and there's probably no server running there.

When netstat says that a local address is LISTENING on 0.0.0.0:64555, that means it accepts a connection via any interface on that port, which is what you want.

So if the server is working with ezTerm on the local loopback with 127.0.0.1:64555, does it also work via your subnet with 192.168.1.xxx:64555? If so, does that work on the Arduino?

One advantage of running an HTTP server is that it is easy to test with a bunch of stuff, like the browser on your phone. But you could try it anyway, and see what it says: http://192.168.1.xxx:64555 Is it more like "Can't connect" or "No response".

You can also try a "one line file server" in various languages, depending on what you have installed, including .NET. If you can get that working on a phone, it should work with Arduino.

My PC is hardwired ethernet to the FiOS router and has ip = 192.168.1.225. The Arduino is connected to the same router by WiFi and shows ip = 192.168.200.2. Using any free port, but I have been favoring 64555, and using the PC ip address as the ezTerm TCP server address (192.168.1.225) - I open the ezServer first to listen as the TCP Server, then start the Arduino sketch and the Arduino serial monitor returns "Failed to connect to TCP server".

In addition to the IP assigned by the router, print the subnet mask

  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Subnet Mask: ");
  Serial.println(WiFi.subnetMask());

There's a good chance it will say

IP Address: 192.168.200.2
Subnet Mask: 255.255.255.0

The mask is a bit mask; long story short, in that case the wired network is a separate subnet from the WiFi network, so "you can't get there from here". With 255.255.255.0, the first three octets have to be the same.

There may be a config option on the router to put everything on the same subnet.

I switched boards from the UnoR4WiFi to a MKR Wifi 1010 (using now WiFiNINA). Same problem. The new Arduino ip and mask is 192.168.200.6 and 255.255.255.0, so it seems the PC (hardwired) and Arduino (Wifi) are on the same subnet. I think my problem is more fundmental. For example, I tried an example WiFiNINA sketch for a "SimpleWebServer" and once run, it waits saying "To see this page in action, open a browser to http://192.168.200.6". I opened browsers (Chrome, Edge, Firefox) to http://192.168.200.6 and just get time outs. My Windows defender is off, my BitDefender is off... It seems this issue must somehow be related to my TCP server issue. Any suggestions where/how to run this down?

Here is the WiFiNINA sketch - very straightforward (even for me)

/*
  WiFi Web Server LED Blink

 A simple web server that lets you blink an LED via the web.
 This sketch will print the IP address of your WiFi module (once connected)
 to the Serial Monitor. From there, you can open that address in a web browser
 to turn on and off the LED on pin 9.

 If the IP address of your board is yourAddress:
 http://yourAddress/H turns the LED on
 http://yourAddress/L turns it off

 This example is written for a network using WPA encryption. For
 WEP or WPA, change the WiFi.begin() call accordingly.

 Circuit:
 * Board with NINA module (Arduino MKR WiFi 1010, MKR VIDOR 4000 and Uno WiFi Rev.2)
 * LED attached to pin 9

 created 25 Nov 2012
 by Tom Igoe
 */
#include <SPI.h>
#include <WiFiNINA.h>

#include "arduino_secrets.h" 
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;                 // your network key index number (needed only for WEP)

int status = WL_IDLE_STATUS;
WiFiServer server(80);

void setup() {
  Serial.begin(9600);      // initialize serial communication
  pinMode(9, OUTPUT);      // set the LED pin mode

  // 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");
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to Network named: ");
    Serial.println(ssid);                   // print the network name (SSID);

    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);
    // wait 10 seconds for connection:
    delay(10000);
  }
  server.begin();                           // start the web server on port 80
  printWifiStatus();                        // you're connected now, so print out the status
}


void loop() {
  WiFiClient client = server.available();   // listen for incoming clients

  if (client) {                             // if you get a client,
    Serial.println("new client");           // print a message out the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out to the serial monitor
        if (c == '\n') {                    // if the byte is a newline character

          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();

            // the content of the HTTP response follows the header:
            client.print("Click <a href=\"/H\">here</a> turn the LED on pin 9 on<br>");
            client.print("Click <a href=\"/L\">here</a> turn the LED on pin 9 off<br>");

            // The HTTP response ends with another blank line:
            client.println();
            // break out of the while loop:
            break;
          } else {    // if you got a newline, then clear currentLine:
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }

        // Check to see if the client request was "GET /H" or "GET /L":
        if (currentLine.endsWith("GET /H")) {
          digitalWrite(LED_BUILTIN, HIGH);               // GET /H turns the LED on
        }
        if (currentLine.endsWith("GET /L")) {
          digitalWrite(LED_BUILTIN, LOW);                // GET /L turns the LED off
        }
      }
    }
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }
}

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  Serial.print("Subnet Mask: ");
  Serial.println(WiFi.subnetMask());


  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
  // print where to go in a browser:
  Serial.print("To see this page in action, open a browser to http://");
  Serial.println(ip);
}

Nope; the first three (of the four) octets are not the same

PC 192.168.1.225
R4 192.168.200.2
1010 192.168.200.6

Wow, OK i thought it was the mask first 3 that had to be the same. I can take the PC and put it on the same wireless to test out. My oissue must be pretty common though where PC hardwired is on different subnet thatn wifi. How can I direct the arduino to handshake with the other subnet?

Let me rephrase that... how can I have an arduino on my wifi subnet send data to my PC on another subnet?

I changed my PC from wired to wifi. New ip address on same subnet: 192.168.200.7 and Arduino is 192.168.200.6. Trying again with ezTerm as TCP Server (same ip as PC, port at 64555) and Arduino as TCPClient - no connection. Also, with WiFiNINA example sketch SimpleWebserver - no connection when I try to open browser to 192.168.200.6.

Can't say I've used a lot of different home routers, but mine do put everything together by default. Some offer "Guest WiFi" on a separate subnet (with a different SSID and password) to specifically isolate guests like visiting in-laws.

The SimpleWebServer looks OK to me. Try connecting with a phone (or laptop) connected to the WiFi. (Verify its IP.)

You can also try some variation on the WiFiWebClient example, which connects to www.google.com, as part of the differential diagnosis.

Hi Ken, Many thanks for your patient help. Very much appreciated. I made sure I was on same subnet but still not connecting. I moved everything to a different laptop (same WiFi LAN) and the TCP sketch works fine. I think that despite my manually turning off Windows firewall and BitDefender, there was something left behind that was blocking TCP from connecting.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.