Mam asynchroniczną klasę serwera UDP z gniazdem powiązanym z adresem IPAddress.Any, i chciałbym wiedzieć, do którego adresu IP odebrany pakiet został wysłany (... lub odebrany). Wydaje się, że nie mogę po prostu użyć właściwości Socket.LocalEndPoint, ponieważ zawsze zwraca ona wartość 0.0.0.0 (co ma sens, ponieważ jest związana z tym ...).C# UDP Socket: Uzyskaj adres odbiornika
Oto interesujących części kodu obecnie używam:
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.
}
Jak wspomniano wcześniej, to zawsze drukuje taką linię:
Odebrane 32 bajtów z 127.0.0.1:1678 do 0.0.0.0: 12345
I chciałbym to być coś takiego:
Odebrane 32 bajtów z 127.0.0.1:1678 do 127.0.0.1:12345
Dzięki, z góry za wszelkie pomysły na ten temat! --Adam
UPDATE
Cóż, znalazłem rozwiązanie, choć nie lubię go ... Zasadniczo, zamiast otwarcie jednego gniazda udp związany IPAddress.Any, tworzę unikalne gniazdo dla każdego dostępnego adresu IP. Tak więc, nowa funkcja Starter wygląda następująco:
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);
}
}
To jest tylko do zilustrowania koncepcji, największy problem z tym kodem, jak jest to, że każde gniazdo stara się wykorzystać ten sam bufor ... co jest generalnie zły pomysł ...
Musi być lepsze rozwiązanie tego; Mam na myśli, że źródło i miejsce docelowe są częścią nagłówka pakietu UDP! No cóż, chyba pójdę z tym, dopóki nie będzie czegoś lepszego.
Zostało przetestowane teraz mate i działa. Jest to zdecydowanie najlepsza odpowiedź na kilka pytań na ten temat. Chciałbym zobaczyć wersję ReceiveMessageFromAsync, ale prawdopodobnie nie rozwiążę tego, jeśli nie odpowiesz. –
@StephenKennedy: Nie sądzę, żebym już miał ten kod, mówiąc szczerze. : P To nie jest strasznie skomplikowane, IIRC; po prostu skonfiguruj 'SocketAsyncEventArgs', dołącz program obsługi do zdarzenia 'Completed', a następnie przekaż obiekt do' ReceiveMessageFromAsync'. – cHao
Bez obaw. Mam funkcję SendToAsync(), więc mogę mieć grę z ReceiveMessageFromAsync() tmw :) Dzięki. –