2012-03-21 27 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

相关问题