Всем привет! Когда сервер отправляет байт данных на уже отключенный клиент то я получаю вот такое исключение:
Kак узнать клиент доступен ли?
Как утсранить эту проблему или обоити
?
Искал в интернете, нашел пару похожих вопросов но у них другие проблемы в конце решил спросить тут.
Server:
byte[] buffer = new byte[1024];
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 23000);
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
EndPoint EP = (EndPoint)sender;
int i;
sock.Bind(ipep);
while (true)
{
try
{
i = sock.ReceiveFrom(buffer, ref EP); // ошибка появляется здесь
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadKey();
break;
}
// нажимаем на любую клаву чтобы получить ошибку
Console.WriteLine("Нажмите любую клавишу чтобы отправить байт клиенту и получить ошибку");
Console.ReadKey();
sock.SendTo(buffer, i, SocketFlags.None, EP);
Client:
int serverPort = 23000;
string hostName = "127.0.0.1";
byte[] buffer = new byte[1024];
EndPoint remote;
IPEndPoint endPoint;
Socket server;
endPoint = new IPEndPoint(IPAddress.Parse(hostName), serverPort);
server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
remote = (EndPoint)sender;
buffer = Encoding.Unicode.GetBytes("me send");
server.SendTo(buffer, 0, buffer.Length, SocketFlags.None, endPoint);
// выходим из клиента чтобы сервер отправил отключенному клиенту;
Ответ
Socket.ReceiveFrom внутри использует функцию recvfrom. Она соотвественно
может завершится с ошибкой WSAECONNRESET(код у неё 10054). В документации на функцию recvfrom указанано следующие описание ошибки WSAECONNRESET
The virtual circuit was reset by the remote side executing a hard or
abortive close. The application should close the socket; it is no
longer usable. On a UDP-datagram socket this error indicates a
previous send operation resulted in an ICMP Port Unreachable message.
В кратце на русском: Если хост разорвет соединение и после этого будет вызыван send, то последующая операция чтения завершится с этой ошибкой.
Соответственно чтобы решить вашу проблему, нужно использовать примерно такой код:
static void Main(string[] args)
{
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) {
byte[] buffer = new byte[1024];
socket.Bind(new IPEndPoint(IPAddress.Any, 23000));
while (true) {
var i = 0;
EndPoint clientPoint = new IPEndPoint(IPAddress.Any, 0);
try {
i = socket.ReceiveFrom(buffer, ref clientPoint);
}
catch (SocketException ex) when (ex.ErrorCode == 10054) {
// ни чего не делаем идем дальше
continue;
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
break;
}
socket.SendTo(buffer, i, SocketFlags.None, clientPoint);
}
}
}
PS:
Есть еще магическая константа SIO_UDP_CONNRESET, которая вроде убирает генерирование этой ошибки. Но я не уверен, что она влияет только на этот случай поэтому код приводить с ней не буду.
Комментариев нет:
Отправить комментарий