Ich habe eine asynchrone UDP-Server-Klasse mit einem Socket auf IPAddress.Any gebunden, und ich möchte wissen, welche IPAddress das empfangene Paket gesendet wurde (... oder empfangen am). Es scheint, dass ich nicht einfach die Socket.LocalEndPoint-Eigenschaft verwenden kann, da es immer 0.0.0.0 zurückgibt (was sinnvoll ist, da es daran gebunden ist ...).C# UDP Socket: Get Empfängeradresse
Hier die interessanten Teile des Codes sind Ich bin derzeit mit:
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.
}
Wie bereits erwähnt, dies immer druckt eine Zeile wie:
Received 32 Bytes von 127.0.0.1:1678 bis 0.0.0.0: 12345
Und ich möchte es so etwas wie sein:
Received 32 Bytes von 127.0.0.1:1678 zu 127.0.0.1:12345
Dank im Voraus für alle Ideen auf diesem! --Adam
UPDATE
Nun, ich habe eine Lösung gefunden, obwohl ich es nicht mag ... Im Grunde genommen, anstatt ein einzelnes UDP-Sockets der Öffnung zu IPAddress.Any gebunden, ich erstellen eindeutiger Socket für jede verfügbare IP-Adresse. So sieht die neue Starter-Funktion wie:
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);
}
}
Das gerade ist das Konzept zu veranschaulichen, das größte Problem mit diesem Code wie es ist, ist, dass jede Steckdose den gleichen Puffer ... verwenden versucht, die in der Regel ist eine schlechte Idee ...
Es muss eine bessere Lösung dafür geben; Ich meine, die Quelle und das Ziel sind Teil des UDP-Paket-Headers! Naja, ich denke, ich werde damit fortfahren, bis es etwas Besseres gibt.
Es wurde jetzt getestet, Partner und es funktioniert. Dies ist bei weitem die beste Antwort auf die verschiedenen Fragen zu diesem Thema. Ich würde gerne die ReceiveMessageFromAsync-Version sehen, aber kann es wahrscheinlich für mich selbst herausfinden, wenn Sie nicht antworten. –
@StephenKennedy: Ich glaube nicht, dass ich diesen Code überhaupt noch habe, um ehrlich zu sein. : P Es ist nicht sehr kompliziert, aber, IIRC; Richten Sie einfach ein 'SocketAsyncEventArgs' ein, fügen Sie einen Handler an sein' Completed' Ereignis an und übergeben Sie das Objekt dann an 'ReceiveMessageFromAsync'. – cHao
Keine Sorge. Ich habe SendToAsync() arbeiten so möglicherweise eine Wiedergabe mit ReceiveMessageFromAsync() tmw :) Danke. –