J4N
J4N

Reputation: 20761

UDP Multicast: Socket.SendTo is blocking

I've an application that send multicast packets.

I use a BlockingCollection to store message that I've to send and then a thread is dedicated to send just iterate over this collection and send message in it. I've a socket for each local IP, since I need to send it on each IP.

It usually works nice, but recently, I had several times my thread hanging on the Socket.SendTo call, causing my application to not respond anymore to any external call. My BlockingCollection get bigger and bigger and is never treated.

I can't find any reason to have this Socket.SendTo call that is blocking my call. If it was a TCP call, I can imagine that there is nobody on the other side, but here with UDP, I don't see any possible issue.

My code is basically:

Debug.WriteLine("Sending message on local endpoint " + socket.Key + ", to " + remoteEndpoint);
int sendTo = socket.Value.SendTo(buffer, remoteEndpoint);
Debug.WriteLine("Successfully sent a packet with "+sendTo+" bytes");

In my logs I see:

[...]
Sending message on local endpoint 10.10.23.56, to 224.0.0.253:5353
Successfully sent a packet with 778 bytes
Sending message on local endpoint 10.9.53.38, to 224.0.0.253:5353
Successfully sent a packet with 778 bytes
Sending message on local endpoint 127.0.0.1, to 224.0.0.253:5353
Successfully sent a packet with 778 bytes
Sending message on local endpoint 10.10.23.56, to 224.0.0.253:5353
Successfully sent a packet with 778 bytes
Sending message on local endpoint 10.9.53.38, to 224.0.0.253:5353
Successfully sent a packet with 778 bytes
Sending message on local endpoint 127.0.0.1, to 224.0.0.253:5353
Successfully sent a packet with 778 bytes
Sending message on local endpoint 10.10.23.56, to 224.0.0.253:5353
Successfully sent a packet with 778 bytes
Sending message on local endpoint 10.9.53.38, to 224.0.0.253:5353¨

I create my socket like this:

Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
sendSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
sendSocket.MulticastLoopback = true;
sendSocket.Bind(new IPEndPoint(localAddress, m_port));
sendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,new MulticastOption(m_multicastAddress, localAddress));

I saw here that it's blocking until all my message is sent, but for what reason my message may be blocked like this? But here, it makes minutes that my call is blocked here.

And what to do? Have a time that dispose the Socket and try to create it again when my packet is not sent?

EDIT: I tried to do the same thing with async send/receive, but it's even worse: I still get blocked on EndReceiveTo, but additionally, it prevent me to kill the process(Access denied and I'm Admin, had to reboot :/)

EDIT After the xaxxon answer, I put this before sending my messages, to see if I've socket on which I can't write or are in error:

List<Socket> socketWrite = socketToUse.Select(s => s.Value).ToList();
List<Socket> socketError = socketToUse.Select(s => s.Value).ToList();
Socket.Select(null, socketWrite, socketError, 1000);
Console.WriteLine("Writeable sockets: " + String.Join(", ", socketWrite.Select(s => s.LocalEndPoint.ToString())));
Console.WriteLine("Sockets in errors: " + String.Join(", ", socketError.Select(s => s.LocalEndPoint.ToString())));

But before I enter I get stuck  on my `SendTo` call, 
Writeable sockets: 10.10.23.56:5353, 10.9.53.38:5353, 127.0.0.1:5353
Sockets in errors:
Sending message on local endpoint 10.10.23.56, to 224.0.0.253:5353
Successfully sent a packet with 93 bytes
Sending message on local endpoint 10.9.53.38, to 224.0.0.253:5353
Successfully sent a packet with 93 bytes
Sending message on local endpoint 127.0.0.1, to 224.0.0.253:5353
Successfully sent a packet with 93 bytes
Writeable sockets: 10.10.23.56:5353, 10.9.53.38:5353, 127.0.0.1:5353
Sockets in errors:
Sending message on local endpoint 10.10.23.56, to 224.0.0.253:5353
Successfully sent a packet with 1162 bytes
Sending message on local endpoint 10.9.53.38, to 224.0.0.253:5353
__HERE I GET STUCK

Upvotes: 2

Views: 2634

Answers (2)

xaxxon
xaxxon

Reputation: 19781

Don't mess around with socket send buffers. There is no possible way to ever get this right for all situations.

Instead, use nonblocking sockets, and check to see if the socket is writeable before sending. This will let you fill up the buffer when there is space available.

Upvotes: 1

Manoj Pandey
Manoj Pandey

Reputation: 4666

Like TCP sockets, even UDP sockets have an outgoing (send) buffer. If that send buffer is full, then even sendTo() call will block. You can try to set the SO_SNDBUF socket option to increase the size of the outgoing send buffer. Yet another reason is if you need to resolve ARP. This can happen, if either the next hop in the route or the destination itself is in the same subnet and there is no ARP entry. Since ARP resolution consists of ARP request/ARP response, it is possible that by the time you receive the ARP response, the sender has already enqueued enough packets to fill the send buffer. I would try to increase the SO_SNDBUF progressively and see if the problem you are running into becomes less severe -- this would help identify that the send buffer is indeed the cause of the blocking issue.

Here is a link that talks about setting SO_SNDBUF. http://msdn.microsoft.com/en-us/library/windows/desktop/ms740476%28v=vs.85%29.aspx

Upvotes: 2

Related Questions