.Net套接字 - 10054错误

时间:2010-12-07 19:25:28

标签: .net sockets udp

我们有一个Windows服务,已经在生产中愉快地运行了一年多。就在最近,它开始给它带来麻烦。我没有套接字编程的经验,但我必须尝试找到问题的原因 - 太棒了!

该服务安装在中央服务器上。它“监听”来自全国各地商店的大约400台服务器的数据。

启动时,服务会获取收集数据所需的商店列表以及商店服务器的ipaddress。然后循环遍历列表并执行以下代码:

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(字节[]&安培;   缓冲区,Int32& bytesTransferred,   IAsyncResult asyncResult)

     

在   System.Net.Sockets.Socket.EndAccept(IAsyncResult的   asyncResult)

     

在   Fujitsu.eCrm.Seoul.PosSocketsService.PosListener.CallbackAccept(IAsyncResult的   ar)in   C:\的Inetpub \ wwwroot的\ PosSocketsService \ PosListener.cs:行   109

第109行如下:

Socket connection = this.EndAccept(ar);

我们看到的行为是POSListners都是在服务启动时启动的。然后在短暂的一段时间后,每一个都被关闭 - 同样的10054异常被提出。

监听器似乎是由监控端口上出现的数据触发的,但是当回调方法尝试创建套接字以便读取数据时 - 窗口无法建立套接字。

有人可以建议采取哪些措施来尝试找出问题的根本原因吗?

2 个答案:

答案 0 :(得分:5)

发生这种情况是因为您的某个客户端因您的服务器断开连接(如果您愿意的话,非常不合适)。

举一个例子,在典型的GUI上应该有Connect / Disconnect按钮。但是,如果用户突然连接并关闭应用程序,则套接字将没有时间终止与服务器的连接。当防火墙启动或存在线路连接问题时,可能会发生这种情况。

在任何情况下,我建议您通过自己关闭套接字(服务器端)来处理带有特定错误代码的SocketException。

答案 1 :(得分:2)

这个设计对我来说很奇怪。你正在发出400个单独的听众,afai可以告诉你。通常套接字服务器会发出一个listen,然后使用发送的一些标识数据或源IP来区分传入的客户端连接(“哪个服务器刚连接?”)。

我看不出这里究竟出了什么问题,但我质疑这个设计。我的猜测是服务器上的资源限制,也许自代码工作以来服务器负载配置文件已经改变。