UDP and TCP at the same code please help

Hello,
help help :fearful:
i work in a projet with mega arduino board and Ethernet sheild,

I have to find IP of unit connected to the network and remote it for START and STOP command.
I use broadcast query on IP 255.255.255.255 in UDP protocole with packet recognized from the unit connected.
after find the unit IP i have to send remote command on unit IP in TCP protocol.

I 'm able to find IP of unit if i remove before START/STOP command line in the code

i’m able to make START/STOP unit with IP fixed to a know unit to remote and then there’s not result in Udp2.remoteIP() !

so it seem’s i 'm not able to used TCP and UDP in a same code… :stuck_out_tongue: >:(

thank if you understand my explanation, i’m french

i give my code

remoteunit.ino (2.32 KB)

I’ve also made a processing code that able to do what i want in arduino :confused:

i give code processing

PROCESSING.pde (3.05 KB)

PROCESSING.pde (3.05 KB)

The ethernet shield will handle UDP and TCP at the same time. I haven't tried a broadcast address with it yet tho. Why are you starting two UDP instances/sockets? Isn't one enough for this? You are sending the packet from port 5048 (Udp), then checking for a response on port 6000 (Udp2). That doesn't make sense. The server device should return the response packet to the port of the sender.

I would insure you have a valid IP before attempting the connection. That could cause a fail.

Does the server you are connecting to return any kind of response? What kind of server is it?

thank’s for your response !

The server device is un instrument of mesure ,
it’s talking to software on PC,
i’ve to make the same…

so i used wireshark and saw that software always sending specific datagram to broadcast IP 255.255.255.255
on port 5048 and instrument response always on port 6000, so if i use only only one UDP with my default port (not 6000) ,i dont show any response.

my real problem is to make UDP for catch the instrument device IP and then be able to send TCP start/stop command no this IP on port 502 (default modbus)

i’m able to catch device IP with UDP if i don’t put Client TCP in sketch…

i’m able to command device with start/stop command on the device IP with TCP client if i don’t put UDP instances/sockets in sketch…

but never able to make UDP for catch the instrument device IP and then be able to send TCP start/stop command no this IP on port 502

Then start one UDP socket using port 6000. Send and receive with that one socket. Have you tried that?

edit: This is also incorrect:

// change this
  Ethernet.begin(mac,locIP, gateway, subnet);
// to this
  Ethernet.begin(mac, locIP, gateway, gateway, subnet);

Yes i will test it tomorrow but i don't think there is a response of device on this same port. I also think i can use a server open on port 6000 and begin udp on 5048 to write, but i dont have enough experience on this

You won't know until you try. I use port 8080 for UDP on both ends, and it works ok.

Read the edit to my previous response about your Ethernet.begin call error.

BTW, if your UDP packet goes through a router and a NAT, the router may change the source port when it changes the source IP. The destination device must respond on the new port to get routed through the router.

NO ROUTER NO NAT Only local with with...

Not a problem. Just letting you know that if that "server" is on the Internet side of a router, there may be problems if it doesn't respond to the remote's source port.

hello , it's me again, ;)

nothing to do,

i made this change Ethernet.begin(mac, locIP, gateway, gateway, subnet);

and try to work with only one UDP on port 5048, hopping remote device response also on sender port, but device really reponse only on port 6000 so i use 2 UDP like before, one listener and the other sender on broadcast 255.255.255.255 so it's work fine for the listener : the condition "if(packetSize){" is true and i can get Udp2.remoteIP(); but in final if i add this in or out the condition "if(packetSize){" Udp.stop(); Udp2.stop(); if (client.connect(destIP, 502)) { Serial.println("START"); client.write(datastart, sizeof(datastart)); client.stop(); } there is no response of the remote device and so the condition "if(packetSize){" is false note : destIP=Udp2.remoteIP();

so in fact i see that if i only comment this //client.write(datastart, sizeof(datastart)); so the condition "if(packetSize){" is true and condition if (client.connect(destIP, 502)) { is also true

I goes crazy :confused:

and try to work with only one UDP on port 5048, hopping remote device response also on sender port, but device really reponse only on port 6000

Why didn't you start one UDP port on port 6000 like I suggested? What is it about port 5048 that has you determined to use it?

hello and thank's for your help again

in setup i put Udp.begin(6000);

in udp write function i put Udp.beginPacket(broadcastIP, 5048);

so it's work fine now with only one udp

but if i want to write on TCP like this

** if(packetSize){** if (client.connect(destIP, 502)) { ** Serial.println("START");** ** client.write(datastart, sizeof(datastart));** ** client.stop();** ** }** ** delay(100);**

condition if(packetSize){ is false :confused:

...

and if i comment the client.write then condition if(packetSize){ is true

if(packetSize){ if (client.connect(destIP, 502)) { Serial.println("START"); //client.write(datastart, sizeof(datastart)); client.stop(); } delay(100);

...

nobody else just help me

The server device is un instrument of mesure ,
it’s talking to software on PC,
i’ve to make the same…

The server receives a message from the Arduino and sends nothing in response? Are you certain the problem is not on the server?

edit: Add this function to your sketch to check the socket status. Maybe you are having trouble there.

#include <utility/w5100.h>

 // in loop()
 if(Serial.available()) {
   if(Serial.read() == 'r') ShowSockStatus();    
 }

//then add this variable and function
byte socketStat[4];

void ShowSockStatus()
{
 for (int i = 0; i < MAX_SOCK_NUM; i++) {
   Serial.print(F("Socket#"));
   Serial.print(i);
   uint8_t s = W5100.readSnSR(i);
   socketStat[i] = s;
   Serial.print(F(":0x"));
   Serial.print(s,16);
   Serial.print(F(" "));
   Serial.print(W5100.readSnPORT(i));
   Serial.print(F(" D:"));
   uint8_t dip[4];
   W5100.readSnDIPR(i, dip);
   for (int j=0; j<4; j++) {
     Serial.print(dip[j],10);
     if (j<3) Serial.print(".");
   }
   Serial.print(F("("));
   Serial.print(W5100.readSnDPORT(i));
   Serial.println(F(")"));
 }
}

Socket status:
0x0 = available
0x14 = waiting for a connection
0x17 = connected
0x1C = connected waiting for close
0x22 = UDP

Hello and thank’s for help again

i’ve test your code,

result status server is 0x17 = connected if i comment the client.write code line

0x0 = available if i don’t comment the client.write code line

for information, i’ve made a similar sketch running well on processing and there’s no problem between UDP and TCP,
in this sketch I made UDP broadcast send packet and take remote ip from the data packet and after made connexion client TCP to this remote address and write packet for start unit.

with processing it’s running fine and doesn’t in arduino sketch !!!

i give you my processing code :o

PROCESSING.pde (3.05 KB)

For my probleme, UDP sending for used the UDP remote IP returned and write on it with TCP Client,
i 've no solution at this time instead using 2 arduinos and 2 ethernet shield on a swith but it’s not a low cost solution ! :money_mouth_face:

I don't have a server that monitors 255.255.255.255, but I cheated using netcat. I used my web client code from the playground and added a udp send and receive to it. I sent the packet to 255.255.255.255, and sent a packet using netcat, and the Arduino received it fine, and continued to connect to the server as a client.

If you plan on using the IP from the udp packet as the server, then you must wait for a udp response from the server before you send any tcp requests. Otherwise, the destination IP of the "server" will not be valid yet.

I used my web client code from the playground and added a udp send and receive to it. I sent the packet to 255.255.255.255, and sent a packet using netcat, and the Arduino received it fine, and continued to connect to the server as a client.

can you post your code please :o

thank’s again

Change the server, servername, and udp stuff.

/*
   Web client sketch for IDE v1.0.1 and w5100/w5200
   Uses GET method.
   Posted October 2012 by SurferTim
   Last modified June 17, 2013
*/

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

#include <utility/w5100.h>

// this must be unique
byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEC };

// change to your server
IPAddress server(1,2,3,4);

//Change to your domain name for virtual servers
char serverName[] = "1.2.3.4";

// change to your server's port
int serverPort = 80;

// Here is my udp stuff
EthernetUDP udp;
int udpPort = 8080;
IPAddress udpDest(255,255,255,255);

EthernetClient client;
int totalCount = 0;
int loopCount = 0;
char pageAdd[32];

void setup() {
  Serial.begin(115200);
  // disable w5100 SPI while starting SD
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  
  // Start ethernet
  Serial.println(F("Starting ethernet..."));

  if(!Ethernet.begin(mac)) Serial.println(F("failed"));
  else Serial.println(F("ok"));

  Serial.println(Ethernet.localIP());

  delay(2000);

  udp.begin(udpPort);
  
  Serial.println(F("Ready"));
}

void loop()
{
  if(loopCount < 30)
  {
    // if loopCount is less than 30, just delay a second
    delay(1000);
  }
  else
  {
    // every thirty seconds this runs
    loopCount = 0;

    // Modify next line to load different page
    // or pass values to server
    sprintf(pageAdd,"/",totalCount);

    // sprintf(pageAdd,"/arduino.php?test=%u",totalCount);

    if(!getPage(server,serverPort,pageAdd)) Serial.print(F("Fail "));
    else Serial.print(F("Pass "));
    totalCount++;
    Serial.println(totalCount,DEC);

    sendUdp();
    ShowSockStatus();
  }    

  loopCount++;
  getUdp();
}

void sendUdp() {
  udp.beginPacket(udpDest,udpPort);
  udp.write("hello");
  udp.endPacket();  
}

void getUdp() {
  int packetSize = udp.parsePacket();
  
  if(packetSize) {
    IPAddress remote = udp.remoteIP();
    Serial.println(remote);
  }
}

byte getPage(IPAddress ipBuf,int thisPort, char *page)
{
  int inChar;
  char outBuf[128];

  Serial.print(F("connecting..."));

  if(client.connect(ipBuf,thisPort) == 1)
  {
    Serial.println(F("connected"));

    sprintf(outBuf,"GET %s HTTP/1.1",page);
    client.println(outBuf);
    sprintf(outBuf,"Host: %s",serverName);
    client.println(outBuf);
    client.println(F("Connection: close\r\n"));
  } 
  else
  {
    Serial.println(F("failed"));
    return 0;
  }

  // connectLoop controls the hardware fail timeout
  int connectLoop = 0;

  while(client.connected())
  {
    while(client.available())
    {
      inChar = client.read();
      Serial.write(inChar);
      // set connectLoop to zero if a packet arrives
      connectLoop = 0;
    }

    connectLoop++;

    // if more than 10000 milliseconds since the last packet
    if(connectLoop > 10000)
    {
      // then close the connection from this end.
      Serial.println();
      Serial.println(F("Timeout"));
      client.stop();
    }
    // this is a delay for the connectLoop timing
    delay(1);
  }

  Serial.println();

  Serial.println(F("disconnecting."));
  // close client end
  client.stop();

  return 1;
}

byte socketStat[MAX_SOCK_NUM];
byte destMac[6];

void ShowSockStatus()
{
  Serial.println();
  for (int i = 0; i < MAX_SOCK_NUM; i++) {
    Serial.print(F("Socket#"));
    Serial.print(i);
    uint8_t s = W5100.readSnSR(i);
    socketStat[i] = s;
    Serial.print(F(":0x"));
    if(s < 16) Serial.print(F("0"));
    Serial.print(s,HEX);
    Serial.print(F(" "));
    Serial.print(W5100.readSnPORT(i));
    Serial.print(F(" D:"));
    uint8_t dip[4];
    W5100.readSnDIPR(i, dip);
    for (int j=0; j<4; j++) {
      Serial.print(dip[j],10);
      if (j<3) Serial.print(".");
    }
    Serial.print(F("("));
    Serial.print(W5100.readSnDPORT(i));
    Serial.print(F(") "));

    W5100.readSnDHAR(i,destMac);
    for (int j=0; j<6; j++) {
      if(destMac[j] < 16) Serial.print(F("0"));
      Serial.print(destMac[j],HEX);
      if (j<5) Serial.print(":");
    }
    
    Serial.println();

  }
}

edit: You will need to modify this code to wait for the UDP packet to start communicating with the server. This was just a test of the UDP and TCP protocols in the same sketch.

Have you considered using the localnet broadcast address instead of 255.255.255.255? If your localnet is 192.168.0.0/24, then the broadcast address is 192.168.0.255.