【问题标题】:C# .NET Socket connection issue - Only one usage of each socket address is normally permittedC# .NET 套接字连接问题 - 每个套接字地址通常只允许使用一次
【发布时间】:2013-03-01 15:28:45
【问题描述】:

我遇到以下问题:

一旦我关闭我的 WM6 应用程序,然后尝试再次启动它,我就会收到以下错误: 在 System.Net.Sockets.Socket.Bind(EndPoint localEP) 通常只允许使用每个套接字地址(协议/网络地址/端口) 在 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());
        }
    }
}

【问题讨论】:

  • 关闭时关闭 myTcpListener。
  • 我愿意,但是我正在调用一些 Dll,这些 Dll 有时会导致应用程序崩溃并且不会调用关闭代码。
  • 您需要更好地处理该错误。只是崩溃并留下您的非托管资源,您会收到此错误。尽管 CLR 为您处理托管对象的内存管理,但您需要为非托管对象执行此操作,例如文件和网络连接。
  • 我的问题是我没有办法处理该方的 DLL,而且用户可能会使应用程序崩溃。我愿意接受有关如何处理第三方崩溃以及如何处理用户进入任务管理器并关闭应用程序的建议。

标签: c# .net windows-mobile compact-framework


【解决方案1】:

是的,您的服务器套接字很可能处于 TIME_WAIT 状态。

您可以访问底层ServerSocket,然后使用SetSocketOption并指定ReuseAddress

【讨论】:

  • 我试试看...我发现 Compact Framework 有一些关于套接字的怪癖,所以我会尝试看看是否可用。
  • 所以在创建listner之后我应该做:myTcpListener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
【解决方案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

【讨论】:

    猜你喜欢
    • 2014-05-29
    • 2014-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-14
    • 2023-03-30
    • 2017-04-23
    • 1970-01-01
    相关资源
    最近更新 更多