У меня есть асинхронный UDP-серверный класс с сокетом, связанным с IPAddress. Любой, и я хотел бы знать, какой IP-адрес отправил полученный пакет (... или полученный). Кажется, что я не могу просто использовать свойство 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.
}
Как уже упоминалось ранее, это всегда печатает строку:
получил 32 байт от 127.0.0.1:1678 до 0.0.0.0: 12345
И я хотел бы, чтобы это было что-то вроде:
получил 32 байт от 127.0.0.1:1678 до 127.0.0.1:12345
Спасибо, заранее за любые идеи по этому вопросу! --Adam
UPDATE
Ну, я нашел решение, хотя мне не нравится это ... В принципе, вместо открытия одного сокета UDP, связанный с IPAddress.Any, я создаю уникальный сокет для каждого доступного IPAddress. Таким образом, новый Starter функция выглядит следующим образом:
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, но, возможно, выработаю ее самостоятельно, если вы не ответите. –
@ StephenKennedy: Я не думаю, что у меня даже есть этот код, если честно. : P Это не очень сложно, хотя, IIRC; просто настройте 'SocketAsyncEventArgs', присоедините обработчик к его событию' Completed', затем передайте объект в 'ReceiveMessageFromAsync'. – cHao
Не беспокойтесь. У меня SendToAsync() работает, поэтому может быть игра с ReceiveMessageFromAsync() tmw :) Спасибо. –