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

StackOverflow https://stackoverflow.com/questions/18961261

  •  29-06-2022
  •  | 
  •  

Question

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!

Was it helpful?

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

OTHER TIPS

You can bind an outbound GSocket to a local address (IP and port) with the g_socket_bind function, just like you do for listening sockets.

Doing that is unlikely to solve your problem though. The projector should send the reply packets to the port from which the request was sent; very rarely you need to bind the client socket to a particular port. Verify what is being sent and received with wireshark or tcpdump.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top