#c# #network-programming
#c# #сетевое программирование
Вопрос:
Я пытаюсь прослушивать UDP-пакеты из неизвестного источника. Но не может привязаться к «неуказанному адресу» (0.0.0.0 или ::)
Я уже пробовал прослушивать ::1. Но из того, что я тестировал, это работает только для локальных подключений, которые не передают сетевой интерфейс.
public async void AwaitDiscoveryReply()
{
try
{
using (var client = new UdpClient(AddressFamily.InterNetworkV6))
{
client.Connect(IPAddress.IPv6Any,4568);
var result = await client.ReceiveAsync();
Debug.WriteLine("Received DR");
var stateProtocol = StateProtocol.FromBytes(result.Buffer);
var robeatsDevice = new RobeatsDevice
{
Id = stateProtocol.DeviceId,
Name = stateProtocol.DeviceName,
EndPoint = client.Client.RemoteEndPoint,
StateProtocol = stateProtocol
};
OnDiscoveryReply(new DeviceDiscoveryEventArgs {RobeatsDevice = robeatsDevice});
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
Это продолжает вызывать исключение: The requested address is not valid in its context [::]:4568
Комментарии:
1. Вы используете IPV4 или IPV6?
2. IPV6, но я не думаю, что это действительно имеет значение в данном случае
3. Тогда порт уже используется. Попробуйте использовать из cmd.exe > Netstat -a, чтобы увидеть, какие порты используются.
4. jdweng — Если адрес уже был привязан, в сообщении об ошибке это будет четко указано.
Ответ №1:
Сокеты UDP не имеют соединения. Методы «Connect» в реализациях сокетов UDP по соглашению (не спрашивайте меня, почему) устанавливают конечные точки по умолчанию / фильтруют трафик. Если вы хотите получать трафик с любого адреса, вам вообще не нужно «подключаться». Используйте конструктор с подписью UdpClient(Int32, AddressFamily) и удалите вызов Connect():
public async void AwaitDiscoveryReply()
{
try
{
using (var client = new UdpClient(4568,AddressFamily.InterNetworkV6))
{
var result = await client.ReceiveAsync();
Debug.WriteLine("Received DR");
var stateProtocol = StateProtocol.FromBytes(result.Buffer);
var robeatsDevice = new RobeatsDevice
{
Id = stateProtocol.DeviceId,
Name = stateProtocol.DeviceName,
EndPoint = client.Client.RemoteEndPoint,
StateProtocol = stateProtocol
};
OnDiscoveryReply(new DeviceDiscoveryEventArgs {RobeatsDevice = robeatsDevice});
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
Комментарии:
1. (кстати, я бы предложил использовать,
Receive()
а неReceiveAsync()
для ясности …)2. Почему это? Из-за ожидания?
3. также это дает мне
System.Net.Sockets.SocketException (0x80004005): A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
4. Я предполагаю, что последнее было выброшено из-под вашего
OnDiscoveryReply()
, которое вы не показываете. Как указано в сообщениях об ошибках, вы должны указать адрес при отправке данных — опять же, потому что UDP не имеет соединения. Мы видим только ваше получение здесь.5.
Receive()
для сокетов в режиме блокировки (по умолчанию, которые вы используете).ReceiveAsync()
для общего случая. Он будет работать как есть, но всегда делает то же самое, что и Receive() , возвращая false .