C# UDP Socket: Get receiver address(C# UDP Socket:获取接收者地址)
问题描述
我有一个异步 UDP 服务器类,其套接字绑定在 IPAddress.Any 上,我想知道接收到的数据包发送到哪个 IPAddress(...或在哪个 IPAddress 上接收).看来我不能只使用 Socket.LocalEndPoint 属性,因为它总是返回 0.0.0.0 (这是有道理的,因为它绑定到那个......).
I have an asynchronous UDP server class with a socket bound on IPAddress.Any, and I'd like to know which IPAddress the received packet was sent to (...or received on). It seems that I can't just use the Socket.LocalEndPoint property, as it always returns 0.0.0.0 (which makes sense as it's bound to that...).
以下是我目前正在使用的代码中有趣的部分:
Here are the interesting parts of the code I'm currently using:
private Socket udpSock;
private byte[] buffer;
public void Starter(){
//Setup the socket and message buffer
udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
udpSock.Bind(new IPEndPoint(IPAddress.Any, 12345));
buffer = new byte[1024];
//Start listening for a new message.
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
}
private void DoReceiveFrom(IAsyncResult iar){
//Get the received message.
Socket recvSock = (Socket)iar.AsyncState;
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int msgLen = recvSock.EndReceiveFrom(iar, ref clientEP);
byte[] localMsg = new byte[msgLen];
Array.Copy(buffer, localMsg, msgLen);
//Start listening for a new message.
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
//Handle the received message
Console.WriteLine("Recieved {0} bytes from {1}:{2} to {3}:{4}",
msgLen,
((IPEndPoint)clientEP).Address,
((IPEndPoint)clientEP).Port,
((IPEndPoint)recvSock.LocalEndPoint).Address,
((IPEndPoint)recvSock.LocalEndPoint).Port);
//Do other, more interesting, things with the received message.
}
如前所述,这总是打印如下一行:
As mentioned earlier this always prints a line like:
Received 32 bytes from 127.0.0.1:1678 to 0.0.0.0:12345
Received 32 bytes from 127.0.0.1:1678 to 0.0.0.0:12345
我希望它是这样的:
Received 32 bytes from 127.0.0.1:1678 to 127.0.0.1:12345
Received 32 bytes from 127.0.0.1:1678 to 127.0.0.1:12345
提前感谢您对此的任何想法!--亚当
Thanks, in advance, for any ideas on this! --Adam
更新
好吧,我找到了一个解决方案,虽然我不喜欢它......基本上,我不是打开一个绑定到 IPAddress.Any 的单个 udp 套接字,而是为每个可用的 IPAddress 创建一个唯一的套接字.因此,新的 Starter 函数如下所示:
Well, I found a solution, though I don't like it... Basically, instead of opening a single udp socket bound to IPAddress.Any, I create a unique socket for every available IPAddress. So, the new Starter function looks like:
public void Starter(){
buffer = new byte[1024];
//create a new socket and start listening on the loopback address.
Socket lSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
lSock.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);
EndPoint ncEP = new IPEndPoint(IPAddress.Any, 0);
lSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref ncEP, DoReceiveFrom, lSock);
//create a new socket and start listening on each IPAddress in the Dns host.
foreach(IPAddress addr in Dns.GetHostEntry(Dns.GetHostName()).AddressList){
if(addr.AddressFamily != AddressFamily.InterNetwork) continue; //Skip all but IPv4 addresses.
Socket s = new Socket(addr.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
s.Bind(new IPEndPoint(addr, 12345));
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
s.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, s);
}
}
这只是为了说明这个概念,这段代码的最大问题是每个套接字都试图使用相同的缓冲区......这通常是一个坏主意......
This is just to illustrate the concept, the biggest problem with this code as is, is that each socket is trying to use the same buffer... which is generally a bad idea...
必须有更好的解决方案;我的意思是,源和目标是 UDP 数据包头的一部分!哦,好吧,我想我会继续这样做,直到有更好的东西.
There has to be a better solution to this; I mean, the source and destination are part of the UDP packet header! Oh well, I guess I'll go with this until there's something better.
推荐答案
我也遇到了同样的问题.我没有看到一种方法,使用 ReceiveFrom
或其异步变体来检索接收到的数据包的目标地址.
I just had the same problem. I don't see a way, using ReceiveFrom
or its async variants, to retrieve the destination address of a received packet.
但是...如果您使用 ReceiveMessageFrom
或其变体,您将获得一个 IPPacketInformation
(参考 ReceiveMessageFrom
和 EndReceiveMessageFrom
,或作为 SocketAsyncEventArgs
的属性传递给 ReceiveMessageFromAsync
中的回调).该对象将包含接收数据包的 IP 地址和接口号.
However...If you use ReceiveMessageFrom
or its variants, you'll get an IPPacketInformation
(by reference for ReceiveMessageFrom
and EndReceiveMessageFrom
, or as a property of the SocketAsyncEventArgs
passed to your callback in ReceiveMessageFromAsync
). That object will contain the IP address and interface number where the packet was received.
(请注意,此代码尚未经过测试,因为我使用的是 ReceiveMessageFromAsync
而不是假冒的 Begin/End 调用.)
(Note, this code has not been tested, as i used ReceiveMessageFromAsync
rather than the fakey-fake Begin/End calls.)
private void ReceiveCallback(IAsyncResult iar)
{
IPPacketInformation packetInfo;
EndPoint remoteEnd = new IPEndPoint(IPAddress.Any, 0);
SocketFlags flags = SocketFlags.None;
Socket sock = (Socket) iar.AsyncState;
int received = sock.EndReceiveMessageFrom(iar, ref flags, ref remoteEnd, out packetInfo);
Console.WriteLine(
"{0} bytes received from {1} to {2}",
received,
remoteEnd,
packetInfo.Address
);
}
注意,你显然应该调用 SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true)
作为设置套接字的一部分,在你之前 Bind
它....ReceiveMessageFrom... 方法将为您设置它,但您可能只会在设置选项后 Windows 看到的任何数据包上看到有效信息.(在实践中,这不是什么大问题——但何时/如果它发生了,原因将是一个谜.最好完全阻止它.)
Note, you should apparently call SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true)
as part of setting up the socket, before you Bind
it. The ...ReceiveMessageFrom... methods will set it for you, but you'll probably only see valid info on any packets Windows saw after the option was set. (In practice, this isn't much of an issue -- but when/if it ever happened, the reason would be a mystery. Better to prevent it altogether.)
这篇关于C# UDP Socket:获取接收者地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:C# UDP Socket:获取接收者地址
基础教程推荐
- 如何激活MC67中的红灯 2022-01-01
- 如何在 IDE 中获取 Xamarin Studio C# 输出? 2022-01-01
- 将 Office 安装到 Windows 容器 (servercore:ltsc2019) 失败,错误代码为 17002 2022-01-01
- 将 XML 转换为通用列表 2022-01-01
- 为什么Flurl.Http DownloadFileAsync/Http客户端GetAsync需要 2022-09-30
- MS Visual Studio .NET 的替代品 2022-01-01
- rabbitmq 的 REST API 2022-01-01
- SSE 浮点算术是否可重现? 2022-01-01
- 有没有办法忽略 2GB 文件上传的 maxRequestLength 限制? 2022-01-01
- c# Math.Sqrt 实现 2022-01-01