title: .Net Sockets - 10054 Error
body: <p>We have a windows service that has been happily running in production for over a year. Just recently it has started giving trouble. I don't have any experience of socket programming but I've got to try and find the cause of the problem - great!</p>
  
  <p>The service is installed on a central server. It "listens" for data coming from approximately 400 servers located in stores across the country.</p>
  
  <p>On starting, the service gets a list of stores it needs to collect data from, along with the ipaddress of the store server. It then loops through the list and executes the following code:</p>
  
  <pre><code>IPEndPoint lep = new IPEndPoint(lipa.AddressList[lipa.AddressList.GetUpperBound(0)], (int)portNumber);
  PosListener posListener = new PosListener(lep,this.pendingBacklog,storeTable,messageList);
  </code></pre>
  
  <p>The constructor for the PosListner is as follows:</p>
  
  <pre><code>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();
     }
  }
  </code></pre>
  
  <p>My understanding is that the constructor registers the method CallbackAccept to be executed whenever traffic is found on the a socket that's being monitored.</p>
  
  <p>This callback method is pasted below:</p>
  
  <pre><code>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();
      }
    }
  </code></pre>
  
  <p>The details of the exception are as follows:</p>
  
  <blockquote>
    <hr>
    
    <p>Exception Type:
    System.Net.Sockets.SocketException</p>
    
    <p>ErrorCode: 10054</p>
    
    <p>Message: An existing connection was
    forcibly closed by the remote host</p>
    
    <p>SocketErrorCode: ConnectionReset</p>
    
    <p>NativeErrorCode: 10054</p>
    
    <p>Data:
    System.Collections.ListDictionaryInternal</p>
    
    <p>TargetSite: System.Net.Sockets.Socket
    EndAccept(Byte[] ByRef, Int32 ByRef,
    System.IAsyncResult)</p>
    
    <p>HelpLink: NULL</p>
    
    <p>Source: System</p>
    
    <p>StackTrace Information</p>
    
    <hr>
    
    <p>at
    System.Net.Sockets.Socket.EndAccept(Byte[]&amp;
    buffer, Int32&amp; bytesTransferred,
    IAsyncResult asyncResult)</p>
    
    <p>at
    System.Net.Sockets.Socket.EndAccept(IAsyncResult
    asyncResult)</p>
    
    <p>at
    Fujitsu.eCrm.Seoul.PosSocketsService.PosListener.CallbackAccept(IAsyncResult
    ar) in
    C:\Inetpub\wwwroot\PosSocketsService\PosListener.cs:line
    109</p>
  </blockquote>
  
  <p>Line 109 is as follows:</p>
  
  <pre><code>Socket connection = this.EndAccept(ar);
  </code></pre>
  
  <p>The behaviour we're seeing is that the POSListners are all started when the service starts. Then after a short period each one is closed - with the the same 10054 exception being raised.</p>
  
  <p>It seems that the listener is triggered by data appearing on the monitored port but when the callback method attempts to create a socket so that the data be read - windows is not able to establish the socket.</p>
  
  <p>Could anyone please suggest what steps could be taken to try and isolate the root cause of the problem?</p>