使用Receive [...]异步方法时获取远程端点信息 - 仅供参考

时间:2016-08-05 22:50:27

标签: c# sockets asynchronous

这是Windows .net 烦恼,花了我2​​天的时间来解决。我发现解决方案非常重要,足以让我自己在SO,即。重新给别人一个清晰的陈述。方法文档。

问题:我没有使用ReceiveAsync()的无连接(UDP)套接字的发件人IP地址。

.net提供了优秀的高性能接收异步方法,这些方法优于BeginGetResponce的传统异步方法链 - > (回调) - > BeginReceive - > (回调) - > EndReceive,因为Receive [...] Async方法重用 SocketAsyncEventArgs 。您可以维护SocketAsyncEventArgs池并将其中任何一个传递给Receive [...] Async。当Receive [...] Async引发Completed回调时,SocketAsyncEventArgs(以及它的Buffer属性)为您提供有效负载。重复使用会影响.net垃圾袋。

但是: SocketAsyncEventArgs。 RemoteEndPoint 会产生异常。和SocketAsyncEventArgs。 ReceiveMessageFromPacketInfo 一样。使用(IPAddress.Any 0)预填充RemoteEndPoint只会导致RemoteEndPoint说0.0.0.0:0 - 没用!执行SetSocketOption(SocketOptionLevel.IP,SocketOptionName.PacketInformation,True)无效。似乎无法获得远程IP地址。

网络是完整的问题。这个,但没有具体的答案。 SO确实存在问题的答案(主要是1好1,现在我知道要寻找什么),但也有很多无关紧要的模糊。

以下答案。

2 个答案:

答案 0 :(得分:2)

ReceiveAsync - 没有去 ReceiveFromAsync - 没有去 ReceiveMessageFromAsync - go

设计&这些方法的外观几乎完全相同。 Ofc首先尝试ReceiveAsync。 ReceiveAsyncWithHeaderInfo引起了我的注意......

一个。沿着这个创建套接字:

GetFolderIcon

B中。另外(伪),做一个:

so = Socket.New(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)

在将套接字绑定到本地端点之前。这并不重要,因为第一个 Completed 回调无论如何都会将其设置为True。但是如果没有提前设置,你将丢失第一个数据包。

℃。为ReceiveMessageFromAsync构造SocketAsyncEventArgs时,将其RemoteEndPoint属性设置为

so.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, True)

如果未设置,则ReceiveMessageFromAsync将崩溃,因此这很关键。 IPAddress.Any和端口0并不重要,.net将在数据进入时更新它们,因此设置RemoteEndPoint仅提供要写入的Microsoft空间。 Halleluja。

(D。并自然地在SocketAsyncEventArgs中创建缓冲区和回调,如各种示例所示)

_ _

MS本可以将此评论添加到禁止方法的文档中:

“如果您需要发件人IP地址(您可能会这样做),请不要使用ReceiveAsync或ReceiveFromAsync,请使用ReceiveMessageFromAsync”。

现在你有一个RemoteEndPoint.Address和Port: - )。

答案 1 :(得分:0)

您必须根据异步接收方法的结果强制转换端点。

var res = await udp.ReceiveAsync();
IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);
endpoint = (IPEndPoint)res.RemoteEndPoint;
var data = Encoding.UTF8.GetBytes("Hi");
await udp.SendAsync(data, data.Length, endpoint);