J'ai une classe de serveur UDP asynchrone avec un socket lié à IPAddress.Any, et j'aimerais savoir à quelle IPAddress le paquet reçu a été envoyé (... ou reçu le). Il semble que je ne peux pas simplement utiliser la propriété Socket.LocalEndPoint, car elle renvoie toujours 0.0.0.0 (ce qui est logique car c'est lié à ça ...).Socket UDP C#: Obtenir l'adresse du destinataire
Voici les parties intéressantes du code que je suis actuellement en utilisant:
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.
}
Comme mentionné plus tôt cette affiche toujours une ligne comme:
reçu 32 octets de 127.0.0.1:1678 à 0.0.0.0:
Et je voudrais que ce soit quelque chose comme:
reçu 32 octets de 127.0.0.1:1678 à 127.0.0.1:12345
Merci à l'avance pour toutes les idées sur ce point! --Adam
MISE À JOUR
Eh bien, je trouve une solution, mais je ne l'aime pas ... En fait, au lieu d'ouvrir une seule prise udp liée à IPAddress.Any, je crée une socket unique pour chaque adresse IP disponible. Ainsi, la nouvelle fonction de démarrage ressemble:
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);
}
}
Ceci est juste pour illustrer le concept, le plus gros problème avec ce code tel qu'il est, est que chaque socket tente d'utiliser le même tampon ... qui est généralement une mauvaise idée ...
Il doit y avoir une meilleure solution à cela; Je veux dire, la source et la destination font partie de l'en-tête de paquet UDP! Eh bien, je suppose que je vais aller avec ça jusqu'à ce qu'il y ait quelque chose de mieux.
Il a été testé maintenant mate et ça marche. C'est de loin la meilleure réponse aux nombreuses questions sur ce sujet. Je serais ravi de voir la version de ReceiveMessageFromAsync mais je peux probablement m'en sortir si vous ne répondez pas. –
@StephenKennedy: Je ne pense même plus avoir ce code, pour être honnête. : P Ce n'est pas très compliqué, cependant, IIRC; configurez simplement un 'SocketAsyncEventArgs', attachez un gestionnaire à son événement' Completed', puis passez l'objet 'ReceiveMessageFromAsync'. – cHao
Pas de soucis. J'ai SendToAsync() fonctionnant ainsi peut avoir un jeu avec ReceiveMessageFromAsync() tmw :) Merci. –