IPAddress.Anyにソケットがバインドされた非同期UDPサーバークラスがあり、受信したパケットがどのIPアドレスに送信されたか(...または受信されたか)を知りたいです。Socket.LocalEndPointプロパティは常に0.0.0.0を返すため、これを使用することはできないようです(これは、それにバインドされているので意味があります...)。
これが私が現在使用しているコードの興味深い部分です:
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.
}
前述のように、これは常に次のような行を出力します。
127.0.0.1:1678から0.0.0.0:12345まで32バイトを受信しました
そして、私はそれが次のようなものになりたいです:
127.0.0.1:1678から127.0.0.1:12345まで32バイトを受信しました
事前に、これに関するアイデアをありがとう! - アダム
アップデート
さて、私はそれが好きではありませんが、解決策を見つけました...基本的に、IPAddress.Anyにバインドされた単一のudpソケットを開く代わりに、使用可能なすべてのIPAddressに対して一意のソケットを作成します。したがって、新しいスターター関数は次のようになります。
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);
}
}
これは概念を説明するためのものであり、このコードの最大の問題は、各ソケットが同じバッファーを使用しようとしていることです...これは一般的に悪い考えです...
これにはもっと良い解決策がなければなりません。つまり、送信元と宛先はUDPパケットヘッダーの一部です。まあ、もっと良いものができるまでこれで行くと思います。