C# Async UDP прослушиватель SocketException
у меня довольно простой асинхронный прослушиватель UDP, настроенный как служба, и он работает довольно хорошо некоторое время, но недавно он разбился на SocketException An existing connection was forcibly closed by the remote host
. У меня три вопроса:--3-->
- что вызывает это? (Я не думал, что UDP-сокеты имеют соединение)
- как я могу дублировать его, для тестирования?
- как я могу чисто обрабатывать исключение, чтобы все продолжало работать?
мой код выглядит примерно так:
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){
try{
//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}",
msgLen,
((IPEndPoint)clientEP).Address,
((IPEndPoint)clientEP).Port);
//Do other, more interesting, things with the received message.
} catch (ObjectDisposedException){
//expected termination exception on a closed socket.
// ...I'm open to suggestions on a better way of doing this.
}
}
исключение создается в recvSock.EndReceiveFrom() строка.
2 ответов
С эта ветка форума, кажется, что сокет UDP также получает сообщения ICMP и выбрасывает исключения, когда они получены. Возможно, это отлично подходит для обновлений статуса низкого уровня, но я нашел это раздражающим.
сначала определите магическое число
public const int SIO_UDP_CONNRESET = -1744830452;
затем установите элемент управления io низкого уровня, чтобы игнорировать эти сообщения:
var client = new UdpClient(endpoint);
client.Client.IOControl(
(IOControlCode)SIO_UDP_CONNRESET,
new byte[] { 0, 0, 0, 0 },
null
);
Я видел эту ошибку с UDP, если пакет каким-то образом усечен или иным образом не полностью доставлен. По крайней мере, я!--4-->думаю вот что происходит. Я никогда не мог воспроизвести его надежно.
Я бы предложил вам поймать SocketException
, зарегистрируйте его (если хотите), а затем утилизируйте этот сокет. Тогда звоните Starter
еще раз:
catch (SocketException)
{
// log error
udpSock.Close();
Starter();
}