Can't Send TCP Packets at all?

I’ve been unable to send a TCP packet to the client, and I can’t figure out why. It says it connects just fine, but I see no packets in Wireshark that are sent.

Here’s the networking code:

client.connect("192.168.8.1",80);
        {
            Serial.println("Connected to camera");
            //Encodes JSON Data so that the camera will understand it.
            //Also adds POST data and sends packet 
            String request = "{\"method\": \"actTakePicture\", \"params\":\"[]\", \"id\": \"1\", \"version\": \"1.0\"}";

            client.println("POST /camera HTTP/1.1");
            client.println("Host: " +  webAddress);
            client.println("Accept: application/json-rpc");
            client.print("Content-Length: ");
            client.println(request.length());
            client.println("Content-Type: application/json-rpc");
            client.println(request);
            Spark.process();

        }

        if (client.connected()) {
            Spark.process();
            // echo all available bytes back to the client
            while (client.available()) {
            server.write(client.read());
            Spark.process();
            response = client.read(); 
            Spark.process();
            }
             Serial.println(response);
        } 
        else {
        // if no client is yet connected, check for a new connection
        client = server.available();
        Spark.process();
        }

I’m also running a UDP client in the background. Here’s a link to the full code:

Thanks for the help. I’m running up on a deadline and I have no idea why this won’t work.

Alright, so I’ve been trying to get this to work for a while now, and I’ve thus far been unsuccessful. The spark core is reporting a connection with the IP address, but wireshark shows no packets actually being sent. I’ve reviewed the examples and can’t find the issue.

Here’s my sample program. It’s the example program, setup in manual mode, configured to send a packet to my router’s IP address (server).

SYSTEM_MODE(MANUAL);
// EXAMPLE USAGE

unsigned int once = 0;
TCPClient client;
IPAddress addr( 0, 0, 0, 0 );
byte server[] = { 192, 168, 1, 254 };


void setup()
{
  // Make sure your Serial Terminal app is closed before powering your Core
    Serial.begin(9600);
    WiFi.on();
    // Connects to a network with a specified authentication procedure.
    // Options are WPA2, WPA, or WEP.
    WiFi.clearCredentials();

    //WiFi.setCredentials("DIRECT-thQ0:DSC-QX10", "1R7WJZ7U", WPA2);
    WiFi.setCredentials("icant", "copycode", WPA);
    WiFi.connect();
    // while(!Serial.available()) Spark.process();

    while (!WiFi.ready()) {
        Serial.println("Waiting for WiFi...");
        Spark.process();
        delay(1000);
    }
}

void loop()
{
  addr = WiFi.localIP();
  WiFi.ping(WiFi.gatewayIP());
  Serial.println(addr);
  if (addr[0] != 0 ||addr[1] != 0 || addr[2] != 0 || addr[3] != 0) 
  {
    //"http://10.0.0.1/sony/camera"
    if (client.connect(server, 80))
    {
      Serial.println("Connected");
      //Encodes JSON Data so that the camera will understand it.
      //Also adds POST data and sends packet 
      //String request = "{\"method\": \"actTakePicture\", \"params\":\"[]\", \"id\": \"1\", \"version\": \"1.0\"}";
      String request = "test";
      client.println("POST HTTP/1.1");
      client.println("Host: 192.168.1.254");
      client.println("Accept:*/*");
      client.print("Content-Length: ");
      client.println(request.length());         
      client.println("Content-Type:application/x-www-form-urlencoded");
      client.println(request);
      //Serial.println(request);
      client.println();
      Spark.process();
      client.flush();
      client.stop();
      Spark.process();
      once = 1;
      Serial.println("Packet Sent");
      delay(500);
    }
    else
    {
      Serial.println("Connection Failed");
    }
  }
  if (client.available())
  {
    char c = client.read();
    Serial.print(c);
  }

  // if (!client.connected())
  // {
  //   Serial.println();
  //   Serial.println("disconnecting.");
  //   client.stop();
  //   for(;;);
  // }
}

Sending this command in curl reports a 200 OK with the entire contents of my router’s configuration page, so I believe that it’s something to do with this mode. Can anyone shed some light on this?

curl -X POST -d "test" 192.168.1.254 -i

Hi @benwis

There are a lot of inconsistent things in your code. Is this really your version or could there be some cut-and-paste errors?

For instance, you server IP is 192.168.1.254 but your Host: line in your request has a very different IP address. Your URL in curl simple but in your core is seems like a different test case with a different Host: and different POST URL. And your Content-Type: is very different.

If you run curl -v for verbose, you can see the exact request that curl is making and make your core do the same thing. I think that would be more likely to be successful.

@bko The host line makes sense, but I still thought I’d see malformed packets being sent out. I think I’ve fixed the code, and I’ve edited the post above. The result is the same, however

With WiFi at the radio level, everybody talks to the AP, not to each other. If this packet is destined for your gateway, it could be that it is not retransmitting it.

You might be able to see it with wireshark in monitor mode, where wireshark takes over your computer’s WiFi interface completely (so you are kicked off of the network temporarily). WiFi cracking tools are also good at doing this.

Can you try sending to a different host on the same network?

Manual mode is new right now and I have had to sprinkle calls to Spark.process() liberally in my code in loop(). Maybe somebody else can comment on that one–I have only played with manual mode a few times. It is always easier for me to get it working in automatic and then move to manual mode in my experience.

2 Likes

@bko I now use MANUAL mode exclusively and I never call Spark.process() unless I know I am connected to the Cloud. So I don’t think it’s necessary.

However, my Cores are not entirely stable, after a few hours sometimes their WiFi stops working: to be on the safe side I call System.reset() every 15mins to ensure the WiFi continues to work. Other than the 15mins resets they are stable. They are not Cloud connected but they only do UDP, not TCP.

I have two contradictory worries:
(1) Perhaps calling Spark.process() is a good idea even if not connected to the Cloud. The omniscient surely would have named the function Spark.cloudProcess() if it were to be called only when Spark.connected() [oops do I mean Spark.cloudConnected()]?
(2) Perhaps calling Spark.process() is a bad idea unless connected to the Cloud.

I have asked questions about these issues but they remain misunderstood or unanswered or perhaps I did not understand the answers.

Heya!

I think you’re right in that calling Spark.process is only necessary in MANUAL mode if you’re maintaining the cloud connection, I think if you follow the code path:

calling Spark.process

winds up here:

That being said, it’s good to frequently check back in with your socket. If you’re frequently dropping connections, might make sense to re-patch your cores, or maybe we can help spot any potential issues if it’s code side.

I hope that helps answer your question! :slight_smile:

Thanks,
David

1 Like

@Dave That’s good to know. So Spark.process() calls are not important.
@bko I’ve changed it to send a packet to google.com, and I still don’t see anything in wirehsark indicating a packet was actually sent.

Maybe someone better versed in the firmware can tell me if there’s some kind of diference between manual mode and automatic mode. Connecting to the cloud while in manual mode seems to cause the code to crash after a few seconds with a flashing red indicator. This doesn’t happen in manual mode without the cloud connection. Diagnostic page seems to indicate one flash is a hard fault.

EDIT: Switching to Automatic mode and removing the WiFi setup code also appears to crash the Core in the same method as described above. Again, no evidence of packets actually being sent. What could be causing this?

It appears to work up until it sucessfully manages to connect to google.com. Then it hard faults, and the cycle repeats. Infuriating.

Has anyone been able to send a TCP packet in manual mode? Wouldn’t this be one of the first tests of the manual mode itself? Here’s the test code again:

SYSTEM_MODE(MANUAL);
// EXAMPLE USAGE

unsigned int once = 0;
TCPClient client;
IPAddress addr( 0, 0, 0, 0 );
byte server[] = { 192, 168, 1, 254 };


void setup()
{
  // Make sure your Serial Terminal app is closed before powering your Core
    Serial.begin(9600);
    WiFi.on();
    // Connects to a network with a specified authentication procedure.
    // Options are WPA2, WPA, or WEP.
    WiFi.clearCredentials();

    //WiFi.setCredentials("DIRECT-thQ0:DSC-QX10", "1R7WJZ7U", WPA2);
    WiFi.setCredentials("Why", "me?", WPA);
    WiFi.connect();
    // while(!Serial.available()) Spark.process();

    while (!WiFi.ready()) {
        Serial.println("Waiting for WiFi...");
        Spark.process();
        delay(1000);
    }
}

void loop()
{
   Spark.process();
  addr = WiFi.localIP();
  WiFi.ping(WiFi.gatewayIP());
  Serial.println(addr);
  if ((addr[0] != 0 ||addr[1] != 0 || addr[2] != 0 || addr[3] != 0) && (once == 0)) 
  {
    //If IP Address, Connect to CLoud
     Spark.connect();
     Spark.process();
     Serial.println("Connected to Cloud")
  }
  if (addr[0] != 0 ||addr[1] != 0 || addr[2] != 0 || addr[3] != 0) 
  {
    Spark.process();
    //"http://10.0.0.1/sony/camera"
    if (client.connect("www.google.com", 80))
    {
      Serial.println("Connected");
      //Encodes JSON Data so that the camera will understand it.
      //Also adds POST data and sends packet 
      //String request = "{\"method\": \"actTakePicture\", \"params\":\"[]\", \"id\": \"1\", \"version\": \"1.0\"}";
      String request = "test";
      client.println("POST HTTP/1.1");
      client.println("Host:192.168.1.254");
      client.println("Accept:*/*");
      client.print("Content-Length: ");
      client.println(request.length());         
      client.println("Content-Type:application/x-www-form-urlencoded");
      client.println(request);
      //Serial.println(request);
      client.println();
      Spark.process();
      client.flush();
      client.stop();
      Spark.process();
      once = 1;
      Serial.println("Packet Sent");
      delay(500);
    }
    else
    {
      Serial.println("Connection Failed");
       Spark.process();
    }
  }
  if (client.available())
  {
    char c = client.read();
    Serial.print(c);
     Spark.process();
  }

  // if (!client.connected())
  // {
  //   Serial.println();
  //   Serial.println("disconnecting.");
  //   client.stop();
  //   for(;;);
  // }
}

Automatic Code

// SYSTEM_MODE(MANUAL);
// EXAMPLE USAGE

unsigned int once = 0;
TCPClient client;
IPAddress addr( 0, 0, 0, 0 );
byte server[] = { 192, 168, 1, 254 };


void setup()
{
  // Make sure your Serial Terminal app is closed before powering your Core
    Serial.begin(9600);
    // WiFi.on();
    // // Connects to a network with a specified authentication procedure.
    // // Options are WPA2, WPA, or WEP.
    // WiFi.clearCredentials();

    // //WiFi.setCredentials("DIRECT-thQ0:DSC-QX10", "1R7WJZ7U", WPA2);
    // WiFi.setCredentials("TechShop WiFi", "creative", WPA);
    // WiFi.connect();
    // while(!Serial.available()) Spark.process();

    while (!WiFi.ready()) {
        Serial.println("Waiting for WiFi...");
        // Spark.process();
        delay(1000);
    }
}

void loop()
{
   // Spark.process();
  addr = WiFi.localIP();
  WiFi.ping(WiFi.gatewayIP());
  Serial.println(addr);
  // if ((addr[0] != 0 ||addr[1] != 0 || addr[2] != 0 || addr[3] != 0) && (once == 0)) 
  // {
  //   //If IP Address, Connect to CLoud
  //    Spark.connect();
  //    Spark.process();
  //    Serial.println("Connected to Cloud")
  // }
  if (addr[0] != 0 ||addr[1] != 0 || addr[2] != 0 || addr[3] != 0) 
  {
    // Spark.process();
    //"http://10.0.0.1/sony/camera"
    if (client.connect("www.google.com", 80))
    {
      Serial.println("Connected");
      //Encodes JSON Data so that the camera will understand it.
      //Also adds POST data and sends packet 
      //String request = "{\"method\": \"actTakePicture\", \"params\":\"[]\", \"id\": \"1\", \"version\": \"1.0\"}";
      String request = "test";
      client.println("POST HTTP/1.1");
      client.println("Host:192.168.1.254");
      client.println("Accept:*/*");
      client.print("Content-Length: ");
      client.println(request.length());         
      client.println("Content-Type:application/x-www-form-urlencoded");
      client.println(request);
      //Serial.println(request);
      client.println();
      // Spark.process();
      client.flush();
      client.stop();
      // Spark.process();
      once = 1;
      Serial.println("Packet Sent");
      delay(500);
    }
    else
    {
      Serial.println("Connection Failed");
       // Spark.process();
    }
  }
  if (client.available())
  {
    char c = client.read();
    Serial.print(c);
     // Spark.process();
  }

  // if (!client.connected())
  // {
  //   Serial.println();
  //   Serial.println("disconnecting.");
  //   client.stop();
  //   for(;;);
  // }
}

Hmm. Some potential issues jump out, could be DNS resolution issues, or google trying to redirect you to https, or Google dumping too much data back over the connection. Could you try on a http server that you have the IP address for, and can watch? Maybe throw a delay after your while (!WiFi.ready()) line just in case something else needs to finish after the dhcp resolution?

Thanks,
David

2 Likes

Alright @dave. I setup a MAMP server on my laptop and set the Spark Core to send packets to that. So here are the results of the tests:

Manual Mode w/ Spark.connect() call: Packet Sent Correctly
Manual Mode without Spark.connect() call: Packet Sent Correctly

Yay! So it’s sending the packets now for some reason. Maybe some update to the Web IDE or maybe a fluke of luck.

When sending to a specific port with TCP and client.connect(), do you include the port in the address as well as after the comma, or just after the comma? Say I wanted to connect to google on port 81, would I do

client.connect(http://google.com:81,81);

or just

client.connect(http://google.com,81);

Code for Manual Mode:

SYSTEM_MODE(MANUAL);
// EXAMPLE USAGE

unsigned int once = 0;
TCPClient client;
IPAddress addr( 0, 0, 0, 0 );
byte server[] = { 192, 168, 1, 153 };


void setup()
{
  // Make sure your Serial Terminal app is closed before powering your Core
    Serial.begin(9600);
    WiFi.on();
    // Connects to a network with a specified authentication procedure.
    // Options are WPA2, WPA, or WEP.
    WiFi.clearCredentials();

    //WiFi.setCredentials("DIRECT-thQ0:DSC-QX10", "1R7WJZ7U", WPA2);
    WiFi.setCredentials("2WI123", "1111111111", WPA);
    WiFi.connect();
    // while(!Serial.available()) Spark.process();

    while (!WiFi.ready()) {
        Serial.println("Waiting for WiFi...");
        Spark.process();
        delay(1000);
    }
}

void loop()
{
   Spark.process();
  addr = WiFi.localIP();
  WiFi.ping(WiFi.gatewayIP());
  Serial.println(addr);
  if ((addr[0] != 0 ||addr[1] != 0 || addr[2] != 0 || addr[3] != 0) && (once == 0)) 
  {
    //If IP Address, Connect to CLoud
     Spark.connect();
     Spark.process();
     Serial.println("Connected to Cloud");
  }
  if (addr[0] != 0 ||addr[1] != 0 || addr[2] != 0 || addr[3] != 0) 
  {
    Spark.process();
    //"http://10.0.0.1/sony/camera"
    if (client.connect(server, 80))
    {
      Serial.println("Connected");
      //Encodes JSON Data so that the camera will understand it.
      //Also adds POST data and sends packet 
      //String request = "{\"method\": \"actTakePicture\", \"params\":\"[]\", \"id\": \"1\", \"version\": \"1.0\"}";
      String request = "test";
      client.println("POST HTTP/1.1");
      client.println("Host:192.168.1.254");
      client.println("Accept:*/*");
      client.print("Content-Length: ");
      client.println(request.length());         
      client.println("Content-Type:application/x-www-form-urlencoded");
      client.println(request);
      //Serial.println(request);
      client.println();
      Spark.process();
      client.flush();
      client.stop();
      Spark.process();
      once = 1;
      Serial.println("Packet Sent");
      delay(500);
    }
    else
    {
      Serial.println("Connection Failed");
       Spark.process();
    }
  }
  if (client.available())
  {
    char c = client.read();
    Serial.print(c);
     Spark.process();
  }

  // if (!client.connected())
  // {
  //   Serial.println();
  //   Serial.println("disconnecting.");
  //   client.stop();
  //   for(;;);
  // }
}

Nice! I think in this case you want to provide only the hostname for DNS resolution, don’t include any protocol details in the hostname field, that would probably confuse the DNS server. so just client.connect("google.com", 81); etc. :slight_smile:

Thanks,
David

1 Like