2013-03-13 19 views
5

我有以下問題的一個用法:C#.NET Socket連接問題 - 每個套接字地址通常允許

一旦我關閉我的WM6應用程序,然後嘗試再次啓動它,我得到這個錯誤: System.Net.Sockets.Socket.Bind(EndPoint localEP)通常只允許每個套接字地址(協議/網絡地址/端口)的一個用法: at System.Net.Sockets.Socket.TcpListener.Start() ...

我認爲這是由於連接超時的時間間隔,所以我會喜歡關閉所有打開的連接,並強制它創建一個新的連接,這是繼續進行的正確方式,還是有不同的方式來處理?

這裏是用來啓動監聽代碼:

/// <summary> 
/// Listens Asynchronously to Clients, creates a recieveMessageHandler to process the read. 
/// 
/// Check WIKI, TODOS 
/// </summary> 
/// <returns></returns> 
public void Listen() 
{ 
    myTcpListener.Start(); 

    while (true) 
    { 
     //blocks until a client has connected to the server 
     try 
     { 
      TcpClient myTcpClient = myTcpListener.AcceptTcpClient(); 
      DateTime now = DateTime.Now; 
      //Test if it's necessary to create a client 
      ClientConnection client = new ClientConnection(myTcpClient, new byte[myTcpClient.ReceiveBufferSize]); 

      // Capture the specific client and pass it to the receive handler 
      client.NetworkStream.BeginRead(client.Data, 0, myTcpClient.ReceiveBufferSize, r => receiveMessageHandler(r, client), null); 
     } 
     catch (Exception excp) 
     { 
      Debug.WriteLine(excp.ToString()); 
     } 
    } 
} 
+0

關閉時關閉myTcpListener。 – 2013-03-13 15:43:31

+0

我這樣做,但是我打電話給一些Dll,有時會導致應用程序崩潰,並且不會調用關機代碼。 – Astronaut 2013-03-13 15:50:06

+0

您需要更好地處理該錯誤。只要崩潰並讓你的非託管資源擱置,你會得到這個錯誤。雖然CLR爲您管理託管對象的內存管理,但您需要爲非託管對象(如文件和網絡連接)執行此操作。 – 2013-03-13 16:16:20

回答

4

是的,你的服務器套接字可能處於TIME_WAIT狀態。

您可以訪問底層ServerSocket,然後使用SetSocketOption並指定ReuseAddress

+0

我給了一個嘗試...我發現Compact Framework有一些套接字的怪癖,所以我會試着去看看它是否可用。 – Astronaut 2013-03-13 15:51:35

+3

所以創建listner後,我應該這樣做: myTcpListener.Server.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress,true); – Astronaut 2013-03-13 16:00:56

2

我在這裏猜測,ClientConnection是你的DLL,因爲我沒有看到已經包含在CF中。如果你聲明MethodInvoker,你並不需要那麼做。

public delegate void MethodInvoker(); // required 

爲了使您的代碼真的華而不實,您還應該創建你自己的EventArgs類:

public class WmTcpEventArgs : EventArgs { 

    private string data; 

    public WmTcpEventArgs(string text) { 
    data = text; 
    } 

    public string Data { get { return data; } } 

} 

很簡單。有了這個新的WmTcpEventArgs類,你應該準備就緒收到您的數據可以發佈到像一個TextBox控制:

private void NetworkResponder(object sender, WmTcpEventArgs e) { 
    textBox1.Text = e.Data; 
} 

而是在你的代碼編碼while(true)的,我更喜歡有一點點布爾變量

private bool abortListener; 

的代碼會是這個樣子:

public void Listen() { 
    listener.Start(); 
    while (!abortListener) { 
    try { 
     using (var client = listener.AcceptTcpClient()) { 
     int MAX = client.ReceiveBufferSize; 
     var now = DateTime.Now; 
     using (var stream = client.GetStream()) { 
      Byte[] buffer = new Byte[MAX]; 
      int len = stream.Read(buffer, 0, MAX); 
      if (0 < len) { 
      string data = Encoding.UTF8.GetString(buffer, 0, len); 
      MethodInvoker method = delegate { NetworkResponder(this, new WmTcpEventArgs(data)); }; 
      abortListener = ((form1 == null) || form1.IsDisposed); 
      if (!abortListener) { 
       form1.Invoke(method); 
      } 
      } 
     } 
     } 
    } catch (Exception err) { 
     Debug.WriteLine(err.Message); 
    } finally { 
     listener.Stop(); 
    } 
    } 
} 

注意你仍然捕捉你的例外,但你也停止TcpListener

相關問題