0

I don't understand that much about network connections. I have followed a lot of example code and it works the first time, but not the second and it makes no sense why.

The "server side" is a PC running Ubuntu 16.04. The "client side" is running LwIP on a TI DSP. Here is the portion of code that works:

/*  find out who is out there  */

usock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if(!usock)
  {
    printf("can't create UDP socket \n");
    exit(-4);
  }

/*  si_me is local receive port  */

  memset((char *) &si_me, 0, sizeof(si_other));
  si_me.sin_family = AF_INET;
  si_me.sin_port = htons(RCVPORT);
  si_me.sin_addr.s_addr = htonl(INADDR_ANY);
  bind(usock, (struct sockaddr*)&si_me, slen);

/*  si_other is broadcast receive port */

  memset((char *) &si_other, 0, sizeof(si_other));
  si_other.sin_family = AF_INET;
  si_other.sin_port = htons(BRDCST);
  inet_aton("192.168.1.255", &si_other.sin_addr);

  setsockopt(usock, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));
  flags = fcntl(usock, F_GETFL);
  flags |= O_NONBLOCK;
  fcntl(usock, F_SETFL, flags);
[...]

    printf("sending %s", sndbuffer);
    if (sendto(usock, sndbuffer, 26, 0 , (struct sockaddr *) &si_other, slen) < 0)
    {
      printf("failed udp sendto\n");
      exit(-5);
    }
    clock_gettime(CLOCK_REALTIME, &rtc);
    ttime = rtc.tv_sec;
    j = 0;
    printf("waiting for response\n");
    while((j <= 0) && (ttime + 10 > rtc.tv_sec))
    {
      j = recvfrom(usock, &rcvbuffer[numBytes], 256, 0, NULL, 0);
      if(j > 0)
      {
    numBytes += j;
    break;
      }
      clock_gettime(CLOCK_REALTIME, &rtc);
    }  
  printf("got %ld bytes\n", numBytes);
  rcvbuffer[24] = 0;
  printf("received %s", rcvbuffer);

The purpose of that block is so the client side knows what ip address the server is on and so the server side knows who is out there. It will need expanding to deal with multiple clients eventually, but one step at a time!

I have tried using a different socket and then tried the same socket which did receive the first time but the same thing happens. The following part works:

/*  far address from response  */

  memset((char *) &si_radar, 0, sizeof(si_radar));
  si_radar.sin_family = AF_INET;
  si_radar.sin_port = htons(LELYPORT);
  inet_aton(&rcvbuffer[7], &si_radar.sin_addr);
  printf("sending to: %s:%d\n", &rcvbuffer[7], LELYPORT);

sprintf(sndbuffer, "  %02d:%02d:%06.3f %05d %02d:%02d:%06.3f\n",
    shr, smn, seconds, i, ehr, emn, econ);
numBytes = sendto(usock, sndbuffer, 34, 0, (struct sockaddr*)&si_radar, slen);
printf("sent %s", sndbuffer);

And then nothing shows up when I call:

while((numBytes < 22) && (i < 10))
{
  j = recvfrom(usock, rcvbuffer, 256, 0, NULL, 0);
  if(j > 0) numBytes += j;
  if(j < 0)
  {
     if(errno != EAGAIN)
         perror("receive error:");
  }

After this I have a clock check and after 30 seconds I attempt to resend. On wireshark I see the outgoing message from the sendto() and also the response from the LwIP/DSP. However, the recv() never gets any response!

I have tried using different ports, different sockets, closing the first socket and creating a new socket, and it never sees the response on the second UDP.

I am assuming there is something trivially obvious I am not seeing, and all the different combinations of attempts have gone around it rather than fix the problem. Some of those combinations include putting &si_radar, &rlen in the recvfrom() instead of NULL, 0, along with things like

  rdrSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if(!rdrSock)
  {
    printf("can't create UDP radar socket \n");
    exit(-4);
  }
/* local address fixed */

  memset((char *) &si_me, 0, sizeof(si_other));
  si_me.sin_family = AF_INET;
  si_me.sin_port = htons(LELYPORT);
  inet_aton("192.168.1.13", &si_me.sin_addr);
  if(bind(rdrSock, (struct sockaddr*)&si_me, slen)<0) perror("bind failed");
  flags = fcntl(rdrSock, F_GETFL);
  flags |= O_NONBLOCK;
  fcntl(rdrSock, F_SETFL, flags);

and then using rdrSock instead of usock. Made no difference.

Does anyone have any idea why? UDP should just send data and get data, especially if it comes in on the port! Thanks, Mike

tadman
  • 208,517
  • 23
  • 234
  • 262
drmike
  • 1
  • I'm guessing this is C code, correct? – tadman Jul 20 '17 at 18:55
  • 'sprintf(sndbuffer, " %02d:%02d:%06.3f %05d %02d:%02d:%06.3f\n" is this 34 bytes, incuding the NUL terminator? Why the magic number 34? In all C network code on SO, the misuse of NUL-terminated strings, and the calls that require them, is extremely common. – Martin James Jul 20 '17 at 19:18
  • Welcome to Stack Overflow. Please read the [About] and [Ask] pages soon. The code shown doesn't compile because of the `[...]` line (and other missing information). That means we don't have an MCVE ([MCVE]) to work with. That makes it hard to determine what you're doing wrong because we have to guess what's in the code you haven't supplied, which could well be where the trouble is. And we have to work too hard to make your code compilable — people won't help you if you leave hurdles in their way. You've not explained or shown the client code that talks to this, either. – Jonathan Leffler Jul 21 '17 at 01:02
  • If you want me to look after you've fixed the code to be an MCVE, then add a comment with `@Jonathan` in it and I'll be notified and will look at it eventually. – Jonathan Leffler Jul 21 '17 at 01:03
  • I left out irrelevant stuff - I figured something would be obvious by looking at the code which was relevant. The number 34 is arbitrary - it comes from using a fixed size and dealing with a Java program that includes characters in front - the \n at the end is arbitrary as well. I wanted a fixed size so I could throw away wrong sized packets. I think it will be better to strip it down to see if I can replicate the error with just a simple loop and not including the irrelevant stuff. If I can't, then what I think is irrelevant - is actually the problem! Thanks! – drmike Jul 21 '17 at 14:17

0 Answers0