2012-03-21 18 views
1

車両追跡アプリケーションでGPSデバイスをリッスンするためのTCPサーバー(Windowsサービスとして実装されている)があります。操作からランダムな時間が経過した後、次のエラーが表示されます。「各ソケットアドレス(プロトコル/ネットワークアドレス/ポート)は通常許可されています。私はそれを使用した後、すべてのソケットを閉鎖していると確信しています。誰も私がWindowsのサーバー2008レジストリ(65534)とTCPTimeWaitDelayの値(30秒)でMaxUserPortの値を持っている問題を教えてもらえますか? 1)メインスレッド: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

最初のコードブロックで例外が発生した後に発生しますか?おそらくtry自体の内部ではなく、finallyブロック内のリスナーをクリーンアップする必要があります。 –

答えて

0

競合状態があります。 mainDone.Setに電話すると、現在のスレッドがEndAcceptの方に移動している間に別のスレッドがBeginAcceptに進むことができます。最初にそこに着きますか?以前の承認を完了する前に受け入れを開始すると、このエラーがポップアップする可能性があります。

修正?あなたはさらに良いことに、同期プリミティブのないシンプルなパターンをたどる

EndAcceptを呼び出す後mainDoneイベントを設定する必要があります。私は一つのhereの輪郭を描く。

関連する問題