c# - Socket.Shutdown 抛出 SocketException

标签 c# sockets serversocket asyncsocket

我正在尝试为我的项目实现异步套接字。这是代码

    public void Start(int listeningPort)
    {
        var ipHostInfo = Dns.Resolve(Dns.GetHostName());
        var ipAddress = ipHostInfo.AddressList[0];
        var localEndPoint = new IPEndPoint(ipAddress, listeningPort);

        _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        _listener.Bind(localEndPoint);
        _listener.Listen(3000);
        Started = true;

        Task.Factory.StartNew(() =>
        {
            while (Started)
            {
                allDone.Reset();

                _listener.BeginAccept(AcceptCallback, _listener);

                allDone.WaitOne();
            }
        });
    }

    public void Stop()
    {
        Started = false;
        _listener.Shutdown(SocketShutdown.Both); //<-- throws SocketException
        _listener.Close(2000);
        _listener = null;
    }

    public void Kick(IClient client)
    {
        try
        {
            Clients.Remove(client);
            client.Socket.Shutdown(SocketShutdown.Both);
            client.Socket.Close();
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }

    private void AcceptCallback(IAsyncResult ar)
    {
        Socket handler = null;
        try
        {
            allDone.Set();

            var listener = (Socket) ar.AsyncState;
            handler = listener.EndAccept(ar);

            var client = new Client(this, handler);
            Clients.Add(client);

            var state = new StateObject();
            state.Socket = handler;
            handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
            var client = ClientBySocket(handler);
            if(handler != null && client != null) Kick(client);
        }
    }

    private void ReadCallback(IAsyncResult ar)
    {
        Socket handler = null;
        try
        {
            var state = (StateObject) ar.AsyncState;
            handler = state.Socket;

            var bytesRead = handler.EndReceive(ar);
            if (bytesRead > 0)
            {
                if (Received != null)
                {
                    var buff = new byte[bytesRead];
                    if (buff[0] == 0)
                    {
                        Stop();
                    }
                    return;
                    Array.Copy(state.Buffer, buff, bytesRead);
                    Debug.WriteLine(Encoding.UTF8.GetString(buff));
                    try
                    {
                        Received(this, new ReceiveArgs(buff));
                    }
                    catch(Exception ex)
                    {
                        Debug.WriteLine(ex.Message);
                    }
                }
            }
            handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
            var client = ClientBySocket(handler);
            if (handler != null && client != null) Kick(client);
        }
    }

但每次我调用 Stop(依次调用 shutdown)(无论客户端是否连接),Socket.Shutdown 都会抛出带有消息的 SocketException

Additional information: A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied

我真的被困在这里了。有人知道我做错了什么吗?

最佳答案

您的监听套接字未连接。我认为这条消息说得很好。每次接受连接时,您都会得到一个独立的新套接字。原始套接字从未连接到任何东西。

只是不要对其调用 Shutdown。

顺便说一句,您的 Accept 循环正在使用异步 IO,然后等待它完成。这是没有意义的。使用同步版本。

关于c# - Socket.Shutdown 抛出 SocketException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23963359/

相关文章:

c# - 多个单词导致自动完成扩展程序出现问题

Python套接字缓冲

perl - 如果子进程手动收割,则 IO::Socket::accept 仅有效一次

java TCP套接字消息中断

c - 连接服务器并在c中使用系统功能时出错

java - 客户端(Java)未连接到服务器(Kotlin)Android Studio,出了什么问题?

c# - 在调用 SaveChanges 之前从 EF 集合中获取对象

c# - 是否可以使一段代码原子化 (C#)?

java - 服务器套接字绑定(bind)到哪里?

c# - 客户端何时适合与 SignalR 服务重新协商?