Cannot Close Socket After BeginAccept Method

2019-02-14 15:23发布

I have a program in c# in which i create a socket, binding it, begin listening and then using beginaccept! but then when I try to close\shutdown the socket I get exceptions from the beginaccept AsyncCallback method!

     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);
            }
}

many thanks!

3条回答
何必那么认真
2楼-- · 2019-02-14 15:25

"To cancel a pending call to the BeginAccept method, close the Socket. When the Close method is called while an asynchronous operation is in progress, the callback provided to the BeginAccept method is called. A subsequent call to the EndAccept method will throw an ObjectDisposedException to indicate that the operation has been cancelled."

Socket.BeginAccept Method (AsyncCallback, Object)

proper way could be :
1) create client socket at server, connect to listening socket, after successful EndAccept close it
2) the way suggested by MSDN is just to handle this exception as is

查看更多
等我变得足够好
3楼-- · 2019-02-14 15:28

When main_socket is closed, OnClientConnect() will be called but main_socket.EndAccept() is supposed to throw an ObjectDisposedException. Perhaps you want to catch that exception and treat it as a "The listener socket has been closed" message.

The other problem with your code is that main_socket is not actually connected to anything. Calling main_socket.Shutdown() in Disconnect_Click() might throw too, but this time it should be a SocketException saying that the socket is not connected. I would remove that main_socket.Shutdown() call.

查看更多
孤傲高冷的网名
4楼-- · 2019-02-14 15:29

Old topic, but one solution is: Keep a local variable, to keep track of when you "close/shutdown" the socket. I use _isShutdown.

When you start listening on the socket, set _isShutDown = False;
Before you close the socket, set _isShutdown = True;

In the EndAccept(iar) function, only call

 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..
}

查看更多
登录 后发表回答