.Net Sockets - Ошибка 10054 - PullRequest
       8

.Net Sockets - Ошибка 10054

1 голос
/ 07 декабря 2010

У нас есть служба Windows, которая успешно работает уже более года.Совсем недавно это стало доставлять неприятности.У меня нет опыта программирования сокетов, но я должен попытаться найти причину проблемы - отлично!

Служба установлена ​​на центральном сервере.Он «прослушивает» данные, поступающие с примерно 400 серверов, расположенных в магазинах по всей стране.

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

IPEndPoint lep = new IPEndPoint(lipa.AddressList[lipa.AddressList.GetUpperBound(0)], (int)portNumber);
PosListener posListener = new PosListener(lep,this.pendingBacklog,storeTable,messageList);

Конструктор для PosListner выглядит следующим образом:

internal PosListener(IPEndPoint lep, int pendingBacklog, Hashtable storeTable, ArrayList messageList) : base(lep.Address.AddressFamily,SocketType.Stream,ProtocolType.Tcp) 
{
   ITraceState trState = PosApplication.Trace.StartProc("PosListener");
   try 
   {         
       // Setup listener
       this.ngcIPAddress = lep.Address.ToString();
       this.ngcPort = lep.Port;
       this.storeTable = storeTable;
       this.storeLock = new ReaderWriterLock();
       this.messageList = messageList;
       this.messageLock = new ReaderWriterLock();
       this.handlerList = new ArrayList();
       this.handlerLock = new ReaderWriterLock();
       this.asyncCallback = new AsyncCallback(this.CallbackAccept);
       this.Bind(lep);
       this.Listen(pendingBacklog);
       // Start listening
       PosApplication.PosSocketsEventLog.WriteEntry("Starting Listener on NGC Port "+this.ngcIPAddress+":"+this.ngcPort);
       PosApplication.Trace.WriteDebug("Starting Listener on NGC Port "+this.ngcIPAddress+":"+this.ngcPort);

       this.BeginAccept(this.asyncCallback,null);
   } 
   catch (Exception e) 
   {
        ExceptionManager.Publish(e);
   } 
   finally 
   {
       trState.EndProc();
   }
}

Насколько я понимаю, конструктор регистрирует метод CallbackAccept длябудет выполняться всякий раз, когда обнаруживается трафик в отслеживаемом сокете.

Этот метод обратного вызова вставляется ниже:

private void CallbackAccept(IAsyncResult ar) 
{
    ITraceState trState = PosApplication.Trace.StartProc("CallbackAccept");
    try 
    {
        // Get the socket that handles the client connection
        Socket connection = this.EndAccept(ar);

        // Start listening for the next client connection
        this.BeginAccept(this.asyncCallback,null);

        string storeIPAddress = ((IPEndPoint)connection.RemoteEndPoint).Address.ToString();
        int storePort = ((IPEndPoint)connection.RemoteEndPoint).Port;
        PosApplication.Trace.WriteDebug("Listener "+this.ngcIPAddress+":"+this.ngcPort+" received connection request from "+storeIPAddress+":"+storePort);            

        // Check the remote end point has a recognised Store IP Address
        this.storeLock.AcquireReaderLock(-1);
        bool isAcceptable;
        try 
        {
            isAcceptable = this.storeTable.Contains(storeIPAddress);
        } 
        finally 
        {
            this.storeLock.ReleaseReaderLock();
        }

        // Close connection and throw exception if the remote end point
        // does not have a recognised Store IP Address
        if (!isAcceptable) 
        {

            connection.Shutdown(SocketShutdown.Both);
            connection.Close();

            CrmServiceException ce = new CrmServiceException(
              "Client",
              "ConfigurationError",
              "PosSocketsService.UnSupportedStoreIPAddress",
              PosApplication.Trace,
              this.ngcIPAddress,
              this.ngcPort.ToString(),
              storeIPAddress,
              storePort.ToString());
              throw ce;
        }

        // Setup a connection handler
        this.handlerLock.AcquireWriterLock(-1);
        try
        {       
            IPosHandler posHandler = PosApplication.ConstructIPosHandler(this,connection);
            this.handlerList.Add(posHandler);
        } 
        finally 
        {
            this.handlerLock.ReleaseWriterLock();
        }

    } 
    catch (ObjectDisposedException) 
    {
        // this object has been disposed by another thread
    } 
    catch (SocketException e) 
    {
        ExceptionManager.Publish(e);
        PosApplication.Trace.WriteDebug("Unexpected Socket Exception Closing Listener "+this.ngcIPAddress+":"+this.ngcPort);
        this.Dispose();
    } 
    catch (Exception e) 
    {
        ExceptionManager.Publish(e);
    } 
    finally 
    {
        trState.EndProc();
    }
  }

Подробности исключения приведены ниже:


Тип исключения: System.Net.Sockets.SocketException

ErrorCode: 10054

Сообщение: существующее соединение было принудительно закрыто удаленным хостом

SocketErrorCode: ConnectionReset

NativeErrorCode: 10054

Данные: System.Collections.ListDictionaryInternal

TargetSite: System.Net.Sockets.Socket EndAccept (Byte [] ByRef, Int32 ByRef,System.IAsyncResult)

HelpLink: NULL

Источник: система

Информация StackTrace


на System.Net.Sockets.Socket.EndAccept (Byte [] & buffer, Int32 & bytesTransferred, IAsyncResult asyncResult)

в System.Net.Sockets.Socket.EndAccept (IAsyncResult asyncResult)

в Fujitsu.eockerSerSerSerSerSer..CallbackAccept (IAsyncResult ar) в C: \ Inetpub \ wwwroot \ PosSocketsService \ PosListener.cs: строка 109

Строка 109 выглядит следующим образом:

Socket connection = this.EndAccept(ar);

Поведение, которое мы 'Мы видим, что все POSListner запускаются при запуске службы.Затем через короткий промежуток времени каждый из них закрывается - с тем же повышением 10054.

Кажется, что слушатель вызван данными, появляющимися на контролируемом порте, но когда метод обратного вызова пытается создать сокет, такчто данные читаются - windows не может установить сокет.

Может кто-нибудь предложить, какие шаги можно предпринять, чтобы попытаться определить причину проблемы?

Ответы [ 2 ]

5 голосов
/ 10 декабря 2010

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

Для примера, в типичном графическом интерфейсе должны быть кнопки Connect / Disconnect.Однако, если пользователь подключается и внезапно завершает работу приложения, сокет не успеет разорвать соединение с сервером.Это может произойти, когда включается брандмауэр или возникают проблемы с подключением к линии.

В любом случае я рекомендую вам обработать исключение SocketException с определенным кодом ошибки, закрыв сокет самостоятельно (на стороне сервера)а также.

2 голосов
/ 07 декабря 2010

Этот дизайн выглядит очень странно для меня.Afai может сказать, что вы выпускаете 400 отдельных прослушиваний.Обычно серверы сокетов выдают одно прослушивание, а затем различают входящие клиентские подключения («какой сервер только что подключен?»), Используя некоторые отправляемые идентификационные данные или исходный IP-адрес.Но я ставлю под сомнение этот дизайн.Я предполагаю, что ресурсы сервера будут ограничены, возможно, профиль загрузки сервера изменился с тех пор, как код работал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...