我有一個異步UDP服務器類,並在IPAddress.Any上綁定了一個套接字,我想知道接收的數據包發送到哪個IPAddress(...或接收)。看來,我不能只使用Socket.LocalEndPoint屬性,因爲它總是返回0.0.0.0(這是有道理的,因爲它是綁定到...)。C#UDP Socket:獲取接收者地址
這裏是我目前使用的代碼有趣的部分:
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收到的32個字節: 12345
而且我想它是這樣的:
收到32個字節127.0.0.1:1678到127.0.0.1:12345
感謝,提前,有這方面的想法! --Adam
UPDATE
嗯,我找到了一個解決方案,但我不喜歡它...基本上,而不是打開勢必IPAddress.Any一個UDP套接字,我創建了一個每個可用的IP地址都有獨特的套接字。因此,新的啓動函數看起來像:
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數據包頭的一部分!哦,我想我會一直這樣做,直到有更好的東西。
它現在已經過測試,它的工作。這是迄今爲止關於此主題的幾個問題的最佳答案。我很想看到ReceiveMessageFromAsync版本,但如果你沒有回答,可能可以解決它。 – 2014-09-06 21:32:27
@StephenKennedy:說實話,我不認爲我已經有了這樣的代碼了。 :P這並不複雜,但是,IIRC;只需設置一個'SocketAsyncEventArgs',將一個處理程序附加到其Completed事件,然後將該對象傳遞給ReceiveMessageFromAsync。 – cHao 2014-09-06 22:19:49
不用擔心。我有SendToAsync()工作,所以可能與ReceiveMessageFromAsync()tmw :)發揮感謝。 – 2014-09-06 22:53:04