在 .NET 核心中终止套接字接收

Terminate socket receive in .NET core

我正在 .NET 核心中编写一个 client/server 套接字库,这只是一个在另一个项目中使用的基本模型。

在客户端,我有三个线程,一个监听,一个发送,一个将收到的消息传回给消费者。

我正在尝试实现关闭客户端的关闭功能。发送和接收函数都是消费者,因此很容易告诉他们检查 ManualResetEvent。

但是,我能找到关闭接收线程的唯一方法是 运行 socket.Shutdown(),因为踏板卡在 socket.Recieve() 中。这会导致在侦听线程中抛出一个 SocketException,它可以被捕获、处理并彻底关闭。但是,当我无法确定 SocketException 的 NativeErrorCode 以了解它关闭的原因时,我的问题就出现了。

我不想通过捕获所有 SocketExceptions 来隐藏错误,只是捕获 NativeErrorCode 10004 错误。 NativeErrorCode 在 SocketException class 中不可访问,但我可以在 IntelliSense 中看到它,有什么想法吗?

 private void ListenThread()
    {
        //Listens for a recieved packet, first thing reads the 'int' 4 bytes at the start describing length
        //Then reads in that length and deserialises a message out of it
        try
        {
            byte[] lengthBuffer = new byte[4];
            while (socket.Receive(lengthBuffer, 4, SocketFlags.None) == 4)
            {
                int msgLength = BitConverter.ToInt32(lengthBuffer, 0);
                if (msgLength > 0)
                {
                    byte[] messageBuffer = new byte[msgLength];
                    socket.Receive(messageBuffer);
                    messageBuffer = Prereturn(messageBuffer);
                    Message msg = DeserialiseMessage(messageBuffer);
                    receivedQueue.Enqueue(msg);
                    receivedEvent.Set();
                    MessagesRecievedCount += 1;
                }
            }
        }
        catch (SocketException se)
        {
            //Need to detect when it's a good reason, and bad, NativeErrorCode does not exist in se
            //if(se.NativeErrorCode == 10004)
            //{

           // }
        }
    }

代替se.NativeErrorCode你可以用se.SocketErrorCode(System.Net.Sockets.SocketError),这样更清楚。

此外,我通常使用异步套接字。它们建立在事件模型上,所以如果有东西到达套接字缓冲区,将调用回调函数

    public void ReceiveAsync()
    {
       socket.BeginReceive(tempBytes, 0, tempBytes.Length, 0, ReadCallback, this);//immediately returns 
    }

    private void ReadCallback(IAsyncResult ar)//is called if something is received in the buffer as well as if other side closed connection - in this case countBytesRead will be 0
    {
       int countBytesRead = handler.EndReceive(ar);
       if (countBytesRead > 0)
       {
           //read tempBytes buffer
       }
    }