【问题标题】:Cannot Close Socket After BeginAccept MethodBeginAccept 方法后无法关闭套接字
【发布时间】:2009-11-08 20:28:04
【问题描述】:

我有一个 C# 程序,我在其中创建一个套接字,绑定它,开始监听,然后使用 beginaccept! 但是当我尝试关闭\关闭套接字时,我从 beginaccept AsyncCallback 方法中得到异常!

     private void start_listening()
        {

            main_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint iplocal = new IPEndPoint(IPAddress.Any, 11150);
            main_socket.Bind(iplocal);
            main_socket.Listen(5);
            main_socket.BeginAccept(new AsyncCallback(OnClientConnect), null);
          }


        private void Disconnect_Click(object sender, EventArgs e)
        {
            main_socket.Shutdown(SocketShutdown.Both);
            main_socket.Close();
        }

        public void OnClientConnect(IAsyncResult asyn)
        {

            try
            {
                clients[connected_clients] = new Client("CHANGEME", "127.0.0.1", this);
                clients[connected_clients].Socket = main_socket.EndAccept(asyn);
                clients[connected_clients].WaitForData();
                main_socket.BeginAccept(OnClientConnect, null);
            }
            catch (SocketException se)
            {
                MessageBox.Show(se.Message);
            }
}

非常感谢!

【问题讨论】:

    标签: c# networking sockets


    【解决方案1】:

    当 main_socket 关闭时,将调用 OnClientConnect(),但 main_socket.EndAccept() 应该抛出 ObjectDisposedException。也许您想捕获该异常并将其视为“侦听器套接字已关闭”消息。

    您的代码的另一个问题是 main_socket 实际上没有连接到任何东西。在 Disconnect_Click() 中调用 main_socket.Shutdown() 也可能会抛出异常,但这一次应该是一个 SocketException,表示套接字未连接。我会删除那个 main_socket.Shutdown() 调用。

    【讨论】:

    • 其实有一个办法:如果在连接的本地端关闭了套接字,Socket.Handle 将是-1。
    • 谢谢大家的回答!我会检查的。所以你说当我因为套接字关闭而被抛出 onclientconnect 时,我应该处理那个 excaption?
    • 正确。捕获 ObjectDisposedException 会处理它。
    • 完美解释!
    【解决方案2】:

    老话题,但一种解决方案是:保留一个局部变量,以跟踪您何时“关闭/关闭”套接字。我用_isShutdown

    当你开始监听套接字时,设置 _isShutDown = False;
    在关闭套接字之前,set _isShutdown = True;

    EndAccept(iar)函数中,只调用

     socket.EndAccept() when _isShutdown is false
    <pre><code>
    
    if (_isShutdown == false)
    {
     someWorkSocket = listenSocket.EndAccept(iaSyncResult);
     //...
    }
    else
    {
    //socket is closed, and we shouldn't use it. Should erase this else clause..
    }
    

    【讨论】:

      【解决方案3】:

      "要取消对 BeginAccept 方法的挂起调用,请关闭 Socket。当异步操作正在进行时调用 Close 方法时,将调用提供给 BeginAccept 方法的回调。A随后对 EndAccept 方法的调用将抛出 ObjectDisposedException 以指示操作已被取消。”

      Socket.BeginAccept Method (AsyncCallback, Object)

      正确的方法可能是:
      1)在服务端创建客户端socket,连接监听socket,EndAccept成功后关闭
      2)MSDN建议的方式就是按原样处理这个异常

      【讨论】:

        【解决方案4】:

        beginaccept 之后是线程在 connEventStatus.WaitOne();状态。您必须通过 connEventStatus.Set(); 取消阻塞线程; .这导致该线程将继续。现在您必须通过 YourSocket.Close() 结束套接字。最后,我处理运行它的线程。但请注意,while 循环不能立即创建新的 beginaccept,您可以通过 connEventStatus.Set(); 取消阻塞线程; :-) .

        就是这样

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-01
          • 2016-04-24
          • 1970-01-01
          • 2015-05-12
          • 1970-01-01
          • 2018-01-20
          • 2018-05-17
          • 2011-02-27
          相关资源
          最近更新 更多