Search code examples
clinuxglibgio

How do I control the outbound port when sending a message via a TCP connection with a GSocket?


I am using C, Linux, and a GIO GSocket to build a small application to communicate with a digital projector via TCP. The socket connects successfully and I am able to send messages to the projector successfully. My problem is that I am not able to receive the automated acknowledgement messages returned by the projector when it receives a command. When I send a message then use g_socket_receive, it blocks and never seems to receive a response.

My suspicion of the problem, based on past similar issues in other languages, is that when I send a message using g_socket_send the message is sent on a random available local port. The projector then automatically replies to the port the message originated from. Not knowing what port it used, I am unable to have my GSocket listen on the correct port. In other languages it's been a simple matter of manually setting my local outbound port so that I knew where the response would come back to. However I have not been able to find any information at all about how to do so with a GSocket.

Can anyone offer any assistance with this, or any thoughts on what else the problem could be that I'm missing?

Thanks!


Solution

  • Your read/receive call most likely blocks because you order to read/receive more bytes than the answer sent is long.

    For testing purpose do something like this:

    int fd = -1;
    /* setup fd */
    char buffer[1024] = {0};
    ssize_t size_buffer = sizeof(buffer) - 1;
    size_t size_read_total = 0;
    ssize_t size_read = 0;
    
    while (size_buffer > size_read_total)
    {
      size_read = read(fd, buffer + size_read_total, 1); /* Wait until exactly one byte had been read. */
      if (-1 = size_read)
      {
        if (EINTR == errno)
        {
          continue;
        }
    
        if ((EAGAIN == errno) || (EWOULDBLOCK == errno))
        {
          continue;
        }
    
        break;  /* Fatal error */
      }
      else (0 == size_read)
      {
        break; /* Connection closed by sending side. */
      }
    
      size_read_total += size_read;
    } 
    
    if (-1 == size_read)
    {
      perror("read() failed");
    }
    else
    {
      printf("Received %zd bytes as: '%s'\n", size_read_total, buffer);
    }