Click to See Complete Forum and Search --> : Binding 2 UDP sockets on same port, connected to different destinations, 1 receives


mickaelcfr
April 29th, 2008, 09:12 PM
Hello,
My application wants to send/recv data to 2 different UDP ports on a remote computer, using the same source port.
So I bind to the same local port which works, and connect to the remote IP : port which works as well, but then randomly only one of the two sockets will receive data from the stack, even though packets are arriving on the network for both.

In this code, the local UDP port is always 13398; the first time this code is called, the destination is 192.168.13.45:6970 and the second time it's 192.168.13.45:6972.
What would cause only one of the sockets to receive data afterwards? Also it's randomly the first or the second one that receive data, but once both sockets are binded and connected, only that random one will receive data.

Thanks!

SOCKET serverSock = ::socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP);
int i=1;
if ( setsockopt(serverSock, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof(i)) != 0 ) {
logger.warn(_T("Could not set SO_REUSEADDR: %s"), GetWSATextError(WSAGetLastError()));
}

SOCKADDR_IN saServer, dest;
memset(&saServer,0,sizeof(saServer));
saServer.sin_family = AF_INET;
saServer.sin_addr.s_addr = INADDR_ANY; // Since this is a server, any address will do
saServer.sin_port = htons(m_manager->GetLocalUDPPort()); // Convert int to a value for the port field
int ret = bind(serverSock, (struct sockaddr *) &saServer, sizeof(saServer));
if (ret != 0) {
logger.warn(_T("Could not bind to udp port 1: %d, %s"), m_manager->GetLocalUDPPort(), GetWSATextError(WSAGetLastError()));
return false;
}

memset(&dest,0,sizeof(dest));
dest.sin_family=AF_INET;
dest.sin_addr.s_addr=m_deviceIP;
dest.sin_port = htons(m_devicePort1);
ret = connect(serverSock, (sockaddr *) &dest, sizeof(dest));
if (ret != 0) {
logger.warn(_T("Failed to connect to udp 1: %s:%d, %s"), inet_ntoa(dest.sin_addr), m_devicePort1, GetWSATextError(WSAGetLastError()));
return false;
}

Edders
April 30th, 2008, 04:03 AM
On UDP there is no underlying connection mechanism as with TCP. This means that even though you have sent a packet to a particular IP address on one of the sockets it did not change anything on the status of your socket. With that I mean that this particular socket did not now become "connected" to the socket on the remote system - as would have been the case with TCP. Each action on the socket (like sending a packet or receiving a packet) stands on its own and has normally no influence on any future actions.

To my knowledge using bind() with the same port number on multiple sockets is undefined. Even in the case of TCP you will not know which socket will receive the connection. You may always receive on only the first, only the last, none at all or on both at the same time - all just depending on the implementation of the parts of the underlying network stack. You may find a way to predict this and then find that things change each time other programs open and close sockets.

One solution I see in this case is to only bind one socket and use that to receive all data. You can process every single packet you receive by using the IP address of the sender to determine where it came from.

mickaelcfr
April 30th, 2008, 01:27 PM
Thanks!
I thought bind+connect would make you be able to choose source and destination address/port then use the socket as TCP for the recv/from and threading but I guess I was wrong and that sucks bad time...
Lots of code and threading logic to rewrite now...

So basically there is no way to do what I'm trying to do with recv/send and a combination of bind/connect???
Only recvfrom and sendto can be used?

Edders
April 30th, 2008, 02:36 PM
You can still use connect(), bind() and recv() instead of bind() and recvfrom(), but it will not make a difference to the way the incoming UDP packets are handled. Using recvfrom() gives you the sender information and as such should simplify your code. But I understood from your other thread that you are observing packet loss with that function?

Anyway, in this thread (http://www.codeguru.com/forum/showthread.php?t=450363) a similar multi-threading UDP based solution is discussed, which may be of help to you.

Richard.J
April 30th, 2008, 03:57 PM
normally, you would not care which local port you are using when you are a client (i. e. when you are using connect()). You would use bind() with a port set to 0, letting the operating system choose a free port for you. Using connect() on UDP connections may be unusual, but allows for the use of recv/send as opposed to recvfrom/sendto.

On the server side, you would of course specify a port for bind(), because that would be the port known to the outside world.

The problem you are seeing is caused by a misunderstanding of the REUSEADDR option. This option is only intended to be used by servers to make sure a crashed server can be restarted (and use the same port known to the outside world) even though the TCP stack has not yet released this port.

jamesalbert
October 8th, 2009, 08:54 AM
Please help ...
I have 2 UDP sockets (Socket1 and Socket2) which are bind to the same port.
I use Socket1 to send (using send) and receive(recvfrom) the client ...and
I use Socket1 to send to the client.

Will I have a problem receivin messages on Socket1 from client...
Please note that i dont use Socket2 to receive message from client ....

Also one more doubt ...is there anyway that the client will come to know I have used 2 sockets to send ...ie I dont intend to let the client know that the messages from Socket1 and Socket2 are from different origins(sockets)...please note that...application layer data will not show any difference....

Waiting for your valuable inputs ......!!!!!!!!!!!!!!!!!!!!!!!!!!!