2012-03-21 58 views
1

我有一個TCP服務器(實現爲Windows服務),用於在車輛跟蹤應用程序中偵聽GPS設備,從其操作的隨機時間段後收到以下錯誤:「每個套接字地址(協議/網絡地址/端口)通常是允許的。「雖然我確信我在使用它之後關閉了每個套接字。所以誰能告訴我這裏有什麼問題我已經在Windows Server 2008註冊表與(65534)的MaxUserPort值,並用(30秒)TCPTimeWaitDelay價值?TCP服務器:「每個套接字地址(協議/網絡地址/端口)只有一個的使用通常是允許的。」

下面是代碼: 1)主線程:

private void MainThread() { 
     byte[] bytes = new Byte[1024]; 

     IPEndPoint localEndPoint = new IPEndPoint(0, this.port); 

     Socket listener = new Socket(AddressFamily.InterNetwork, 
      SocketType.Stream, ProtocolType.Tcp); 
     // Addedd on [20/03/2012] by Sherif Mosaad for handling socket exceptions ... 
     //listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1); 

     try { 
      listener.Bind(localEndPoint); 
      listener.Listen(100); 

      while (active) { 
       mainDone.Reset(); 

       listener.BeginAccept(new AsyncCallback(AcceptCallback),listener); 

       while (active) 
        if (mainDone.WaitOne(100, true)) 
         break; 
      } 
      listener.Shutdown(SocketShutdown.Both); 
      listener.Close(); 
      Thread.Sleep(2000); 

     } catch (Exception e) { 
      if (OnError != null) 
       OnError(this, e.ToString()); 
      LogManager.LogError(e, "TCPSimpleServer MainThread"); 
     } 
    } 

2)AcceptCallback處理程序:

private void AcceptCallback(IAsyncResult ar) { 
     mainDone.Set(); 

     Socket listener = (Socket)ar.AsyncState; 
     Socket handler = null; 
     try 
     { 
      handler = listener.EndAccept(ar); 
     } 
     catch 
     { 
      try 
      { 
       listener.Shutdown(SocketShutdown.Both); 
       listener.Close(); 
       Thread.Sleep(2000); 
      } 
      catch { return; } 
     } 

     if (OnConnect != null) 
      OnConnect(this, handler); 

     StateObject state = new StateObject(); 

     state.workSocket = handler; 
     state.endPoint = (IPEndPoint)handler.RemoteEndPoint; 
     stateObjectDictionary.Add(state, state.workSocket); 
     handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
      new AsyncCallback(ReadCallback), state); 
    } 

3)ReadCallback處理程序:

private void ReadCallback(IAsyncResult ar) { 
     String content = String.Empty; 
     StateObject state = (StateObject)ar.AsyncState; 
     Socket handler = state.workSocket; 

     int bytesRead = 0; 
     try 
     { 
      bytesRead = handler.EndReceive(ar); 
     } 
     catch (Exception e) 
     { 
      // Connection closed by client 
      if (OnDisconnect != null) 
       OnDisconnect(this, state.endPoint); 
      return; 
     } 

     if (bytesRead > 0) 
     { 
      string data = Encoding.ASCII.GetString(state.buffer, 0, bytesRead); 
      if (OnDataAvailable != null) 
       OnDataAvailable(this, handler, data); 
      try 
      { 
       handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
        new AsyncCallback(ReadCallback), state); 
      } 
      catch (Exception e) 
      { 
       // Connection closed by client 
       if (OnDisconnect != null) 
        OnDisconnect(this, state.endPoint); 
       return; 
      } 
     } 
     else 
     { 
      // Connection closed by peer 
      if (OnDisconnect != null) 
       OnDisconnect(this, state.endPoint); 
     } 
    } 

最後狀態對象:

public class StateObject 
    { 
     public Socket workSocket = null; 
     public const int BufferSize = 1024; 
     public byte[] buffer = new byte[BufferSize]; 
     public StringBuilder sb = new StringBuilder(); 
     public IPEndPoint endPoint; 
    } 

任何幫助嗎?

+1

是否發生在你的代碼的第一個塊異常後發生?你應該在finally塊中清理你的監聽器,而不是在try裏面。 – 2012-03-21 20:36:22

回答

0

有一個競爭條件。您可以撥打mainDone.Set,以便在當前線程朝EndAccept移動時允許另一個線程前進至BeginAccept。哪個會先到那裏?如果您在完成前一個接受之前開始接受,我懷疑此錯誤可能會彈出。

修復?您需要後設置mainDone事件你叫EndAccept

更妙的是,無需遵循同步原語一個簡單的模式。我概述了一個here

相關問題