Вопрос

Хорошо, у меня есть странное исключение из моего кода, которое беспокоит меня целую вечность.

System.Net.Sockets.SocketException: A blocking operation was interrupted by a call to WSACancelBlockingCall
   at System.Net.Sockets.Socket.Accept()
   at System.Net.Sockets.TcpListener.AcceptTcpClient()

MSDN не очень помогает в этом : http://msdn.microsoft.com/en-us/library/ms741547 (ПРОТИВ 85).aspx и я даже не знаю, с чего начать устранение неполадок в этой ситуации.Он запускается всего 4-5 раз в день, и никогда в нашей тестовой среде.Только на производственных площадках, причем на ВСЕХ производственных площадках.

Я нашел множество сообщений с вопросами об этом исключении, но никаких реальных окончательных ответов о том, что его вызывает и как с ним справиться или предотвратить, нет.

Код выполняется в отдельном фоновом потоке, метод запускается :

public virtual void Startup()
    {
     TcpListener serverSocket= new TcpListener(new IPEndPoint(bindAddress, port));    
        serverSocket.Start();

затем я запускаю цикл, помещая все новые соединения в качестве заданий в отдельный пул потоков.Это становится сложнее из-за архитектуры приложения, но в основном:

   while (( socket = serverSocket.AcceptTcpClient()) !=null) //Funny exception here
    {
         connectionHandler = new ConnectionHandler(socket, mappingStrategy);
         pool.AddJob(connectionHandler);
    }
  }

Оттуда, в pool имеет свои собственные потоки, которые выполняют каждое задание в своем собственном потоке отдельно.

Насколько я понимаю, AcceptTcpClient() - это блокирующий вызов, и каким-то образом winsock сообщает потоку прекратить блокировку и продолжить выполнение..но почему?И что я, по-твоему, должен делать?Просто перехватить исключение и проигнорировать его?


Ну, я действительно думаю, что какой-то другой поток закрывает сокет, но это, конечно, не из моего кода.Что я хотел бы знать, так это:закрыт ли этот сокет подключающимся клиентом (на другой стороне сокета) или он закрыт моим сервером.Потому что на данный момент, всякий раз, когда возникает это исключение, оно отключает мой порт прослушивания, фактически закрывая мою службу.Если это делается из удаленного места, то это серьезная проблема.

В качестве альтернативы, может ли это быть просто сервер IIS, завершающий работу моего приложения и, таким образом, отменяющий все мои фоновые потоки и методы блокировки?

Это было полезно?

Решение

Возможно ли, что ServerSocket закрывается из другого потока?Это вызовет это исключение.

Другие советы

Это мой пример решения, позволяющего избежать WSAcancelblablabla:Определите свой поток как глобальный, тогда вы можете использовать метод invoke следующим образом:

private void closinginvoker(string dummy)
    {
        if (InvokeRequired)
        {
            this.Invoke(new Action<string>(closinginvoker), new object[] { dummy });
            return;
        }
        t_listen.Abort();
        client_flag = true;
        c_idle.Close();
        listener1.Stop();
    }

После того, как вы вызовете его, сначала закройте поток, затем установите флаг forever loop, чтобы он блокировал дальнейшее ожидание (если он у вас есть), затем закройте tcpclient и остановите прослушиватель.

Это может произойти на serverSocket.Stop().Которому я звонил всякий раз, когда Dispose был призван.

Вот как выглядела моя обработка исключений для потока прослушивания:

try
{
    //...
}
catch (SocketException socketEx)
{    
    if (_disposed)
        ar.SetAsCompleted(null, false); //exception because listener stopped (disposed), ignore exception
    else
        ar.SetAsCompleted(socketEx, false);
}

Теперь случилось то, что время от времени такое исключение возникало и раньше _disposed было установлено значение true.Поэтому решение для меня состояло в том, чтобы сделать все потокобезопасным.

То же самое и здесь!Но я выяснил, что ReceiveBuffer на стороне сервера был затоплен клиентами!(В моем случае куча RFID-сканеров, которые продолжали рассылать спам с кодом тега, вместо того, чтобы прекратить отправку до поступления следующего кода тега)

Это помогло увеличить буферы приема и перенастроить сканеры...

Совсем недавно я видел это исключение при использовании HttpWebRequest для размещения большого файла, и время ожидания было пройдено.

Используя следующий код, пока ваше время загрузки > 3 секунд, это вызовет эту ошибку, насколько я мог видеть.

string path = "Reasonably large file.dat";
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
System.Net.HttpWebRequest req = (HttpWebRequest)System.Net.HttpWebRequest.Create("Some URL");
req.Method = "PUT";
req.Timeout = 3000; //3 seconds, small timeout to demonstrate
long length = new System.IO.FileInfo(path).Length;
using (FileStream input = File.OpenRead(path))
{
    using (Stream output = req.GetRequestStream())
    {
        long remaining = length;
        int bytesRead = 0;
        while ((bytesRead = input.Read(buffer, 0, (int)Math.Min(remaining, (decimal)bufferSize))) > 0)
        {
            output.Write(buffer, 0, bytesRead);
            remaining -= bytesRead;
        }
        output.Close();
    }
input.Close();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top