views:

41

answers:

2

I have a connection protocol that has been defined by our customer. Data are sent between two linux computers using UDP and TCP protocols. The IP addresses and ports are fixed on startup.

We are sending messages at 200 Hz and I have been using connect to save some time on the transmissions.

My problem is that if there is a communication error, I need to tear down the connections and reinitialise.

I have a problem with one of the UDP connections as it will not rebind to the required address and returns errno 22.

The code I am using is something like:

int  
doConnect(int& sock, int local_port, char *local_ip, int remote_port, char *remote_ip)  
{  
    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);  
    struct sockaddr_in addr;  

    memset(&addr, 0, sizeof(sockaddr_in);  
    addr.sin_family = AF_INET;  
    addr.sin_port = htons(local_port);  
    inet_pton(local_ip,&addr.sin_addr.s_addr); 

    if (0 > bind(sock, (struct sockaddr*)&addr, sizeof(addr)))  
    {
        printf("Bind Error errno = %d\n", errno);
        return ERR_BIND;  
    }

    memset(&addr, 0, sizeof(sockaddr_in);  
    addr.sin_family = AF_INET;  
    addr.sin_port = htons(remote_port);  
    inet_pton(remote_ip,&addr.sin_addr.s_addr); 

    if (0 > connect(sock, (struct sockaddr*)&addr, sizeof(addr)))  
    {
        printf("Connect Error errno = %d\n", errno);
        return ERR_CONNECT;  
    }
    return ERR_OK;
}

The way that this is used is like this:

int s1(-1), s2(-1);  
doConnect(s1, 31003, "172.17.21.255", 31006, "172.17.21.1");  
doConnect(s2, 31001, "172.17.21.3", 31004, "172.17.21.1");  

When an error occurs

close(s1);
close(s2);

doConnect(s1, 31003, "172.17.21.255", 31006, "172.17.21.1");
doConnect(s2, 31001, "172.17.21.3", 31004, "172.17.21.1");

Here the local address is 172.17.21.3 and I am connecting to 172.17.21.1. s1 listens to a broadcast message.

s1 successfully reconnects to the remote machine, but s2 fails with error 22 from the call to bind.

I have tried explicitly calling bind and connect to an AF_UNSPEC address immediately before I close the socket. This doesn't solve the problem.

Are there any options that I should be using?

A: 

The underlying socket layer might hold the port & IP address still open, even after your call to close. Try some of the following:

  • do a sleep(10) (or more) between the close and the call to doConnect again
  • configure the sockets using setsockopt with the SO_LINGER set to off

This actually happens more commonly with TCP connections, but I see no reason UDP can't have this problem as well.

Eli Iser
+2  A: 

Perhaps you could try:

 int val = 1;
 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));

I also suggest you double check that you're not passing the same socket to the two consecutive doConnect() calls (as errno 22 = EINVAL, which in the case of bind() appears to mean that the socket is already bound to an address).

Martin Törnwall