c# - UDP 多播 : Socket. SendTo 被阻止

标签 c# .net sockets udp multicast

我有一个发送多播数据包的应用程序。

我使用 BlockingCollection 来存储我要发送的消息,然后一个线程专门用于发送,仅迭代此集合并在其中发送消息。我为每个本地 IP 有一个套接字,因为我需要在每个 IP 上发送它。

它通常工作得很好,但最近,我的线程多次卡在 Socket.SendTo 调用上,导致我的应用程序不再响应任何外部调用。我的 BlockingCollection 变得越来越大,但从未得到处理。

我找不到任何理由让这个 Socket.SendTo 调用阻塞我的调用。如果是 TCP 调用,我可以想象另一端没有人,但这里使用 UDP,我看不到任何可能的问题。

我的代码基本上是:

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

在我的日志中我看到:

[...]
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¨

我像这样创建套接字:

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

我看到了here在我的所有消息发送完毕之前它会被阻止,但是出于什么原因我的消息可能会像这样被阻止?但在这里,我的电话几分钟就被屏蔽了。

该怎么办?当我的数据包未发送时,是否有时间处理 Socket 并尝试再次创建它?

编辑:我尝试对异步发送/接收做同样的事情,但更糟糕的是:我仍然在 EndReceiveTo 上被阻止,但此外,它阻止我终止进程(访问被拒绝,我是管理员,有重新启动:/)

编辑 在 xaxxon 回答之后,我在发送消息之前将其放入,以查看是否有无法写入或错误的套接字:

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

最佳答案

与 TCP 套接字一样,甚至 UDP 套接字也有一个传出(发送)缓冲区。如果发送缓冲区已满,则即使 sendTo() 调用也会阻塞。您可以尝试设置 SO_SNDBUF 套接字选项来增加传出发送缓冲区的大小。还有一个原因是您是否需要解析 ARP。如果路由中的下一跳或目标本身位于同一子网中并且没有 ARP 条目,则可能会发生这种情况。由于 ARP 解析由 ARP 请求/ARP 响应组成,因此当您收到 ARP 响应时,发送方可能已经将足够的数据包放入队列以填充发送缓冲区。我会尝试逐步增加 SO_SNDBUF 并查看您遇到的问题是否变得不那么严重 - 这将有助于确定发送缓冲区确实是阻塞问题的原因。

这是一个讨论设置 SO_SNDBUF 的链接。 http://msdn.microsoft.com/en-us/library/windows/desktop/ms740476%28v=vs.85%29.aspx

关于c# - UDP 多播 : Socket. SendTo 被阻止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18787698/

相关文章:

c# - 带截断的多行标签

.net - .NET能保证正则表达式匹配的顺序吗?

javascript - 如何将视频(从 getUserMedia)发送到 Node.js 服务器?

python - 使用 python 创建 SSL 套接字

c# - HttpClient 从不在 IIS 上发送请求

c# - .net 项目和设计器文件的属性错误被锁定

c# - 在 Repository<T> 中返回 Queryable<T> 或 List<T>

c# - 使用 .NETStandard 时不会将 Nuget 包复制到输出

c# - 如何检测到我尝试通过 TLS 安全套接字发送数据失败?

c# - .NET中的语音识别器日期时间