Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当我的插座断开连接时,为什么我要接收数据?_C#_Sockets_Asynchronous - Fatal编程技术网

C# 当我的插座断开连接时,为什么我要接收数据?

C# 当我的插座断开连接时,为什么我要接收数据?,c#,sockets,asynchronous,C#,Sockets,Asynchronous,我的插座有问题。 基本上,我有几个监听器可以在我电脑上的所有可用端口上进行监听。当一个套接字连接到其中一个监听器时,我打开一个新的套接字连接来处理该连接,我的监听器就会返回到监听状态 然而,当客户端断开连接时,我会继续接收空数据。 正如您在下面的代码中所看到的,我放置了一个Console.WriteLine来检查所接收消息的长度。 当连接关闭时,它显示了超过100行的charLen:0。意思是它收到了一些东西,但我不知道它从哪里来 然后我还将在WaitData-方法中收到一个System.Obj

我的插座有问题。 基本上,我有几个监听器可以在我电脑上的所有可用端口上进行监听。当一个套接字连接到其中一个监听器时,我打开一个新的套接字连接来处理该连接,我的监听器就会返回到监听状态

然而,当客户端断开连接时,我会继续接收空数据。 正如您在下面的代码中所看到的,我放置了一个Console.WriteLine来检查所接收消息的长度。 当连接关闭时,它显示了超过100行的
charLen:0
。意思是它收到了一些东西,但我不知道它从哪里来

然后我还将在
WaitData
-方法中收到一个
System.ObjectDisposedException
错误

        ClientSocketClass tmpClient = (ClientSocketClass)asyn.AsyncState;
        try
        {

            // END THE BeginReceive() ASYNCHRONOUS CALL BY CALLING THE EndReceive() METHOD FOR THAT SOCKET
            // THIS WILL RETURN THE NUMBER OF CHARACTER WHICH HAS BEEN RECEIVED BY THE CLIENT
            int byteMessage = tmpClient.Socket.EndReceive(asyn);

            char[] chars = new char[byteMessage + 1];

            // EXTRACT THE CHARACTERS INTO A BUFFER
            System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
            int charLen = d.GetChars(tmpClient.BufferSize, 0, byteMessage, chars, 0);

            Console.WriteLine("charlen: " + charLen.ToString());

            // START WAITING AGAIN FOR NEW DATA FROM THE CLIENT
            WaitForData(tmpClient);

            Array.Resize(ref chars, charLen);

            // PROCESS THE CURRENT MESSAGE
            string tempData = new string(chars).Replace("\0", string.Empty);

            // LOG THE RECEPTION OF NEW DATA
            string log = string.Format("{0}{1}Received: {2}", DateTime.Now.ToString("HH:mm:ss.fff"), "\t", tempData);
            Log(LoggingType.Data, LoggingLevel.Debug, log);


            // ADD THE MESSAGE TO THE MESSAGE QUEUE
            if (MessageQueue != null)
            {
                if (tempData != null && tempData != string.Empty)
                {
                    MessageQueue.Add(tempData);
                }
            }
        }
        catch (ObjectDisposedException)
        {
            // THIS CODE WILL BE EXECUTED IF THE SOCKET WAS DISCONNECTED
            if (tmpClient != null)
            {
                // GET THE ID OF THE CLIENT
                int clientId = tmpClient.Id;

                // REMOVE THE CLIENT FROM THE CONNECTED CLIENTS LISTS
                removeClient(clientId);

                string log = string.Format("{0}{1}Client {2} disconnected", DateTime.Now.ToString("HH:mm:ss.fff"), "\t", clientId);
                Log(LoggingType.Status, LoggingLevel.Notification, log);
            }

            return;
        }
下面是WaitForData方法:

    public void WaitForData(ClientSocketClass selectedClient)
    {
        try
        {
            if (pfnWorkerCallBack == null)
            {
                // SPECIFY THE CALL BACK FUNCTION WHICH SHOULD BE RUN
                // WHEN DATA IS RECEIVED FROM THE CLIENT
                pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
            }

            // START RECEIVING THE MESSAGE INTO THE DATA BUFFER
            selectedClient.Socket.BeginReceive(selectedClient.BufferSize, 0, selectedClient.BufferSize.Length, SocketFlags.None, pfnWorkerCallBack, selectedClient);
        }
        catch (SocketException ex)
        {
            string log = string.Format("{0}\t<WaitForData>\tAn error occured while waiting for data: {1}{2}", DateTime.Now.ToString("HH:mm:ss.fff"), ex.Message, Environment.NewLine);
            Log(LoggingType.Error, LoggingLevel.Debug, log);
        }
    }

该类在BindingList中使用,BindingList显示在DataGridView中,以显示连接的客户端。但是我只显示了Id和IP地址,因此我在StackOverflow()上找到了答案

我没有意识到的是WaitForData实际上生成了一个循环,当我接收NULL时,我需要跳出这个循环

因此,只要添加下面的代码,问题就解决了

    if (byteMessage <= 0)
    {
        // LEAVE THE LOOP
        return;
    }

if(byteMessage接收零字节表示传输结束。在此之后,您不应尝试接收更多字节。OnDataReceived的代码在哪里?请使用cmd.exe>Netstat-a检查客户端和服务器上的连接状态,以查看是否断开连接。连接应仅从客户端(而不是服务器)关闭如果客户端和服务器同时尝试关闭,则存在竞争条件,此时连接可能会半开半关。连接是TCP,需要对每条消息进行确认(包括打开和关闭)。如果客户端和服务器同时关闭,其中一个ACK将不会发生,因为连接的一侧已关闭。显示的第一个代码是onDataReceived。我只是从客户端关闭。服务器不会断开连接,它只会在之后进行清理,并将客户端从connectedClients-list中删除。同时,我我在SO()上发现了一个类似的问题,但我不确定如何在代码中实现它。
    if (byteMessage <= 0)
    {
        // LEAVE THE LOOP
        return;
    }
    public void OnDataReceived(IAsyncResult asyn)
    {
        ClientSocketClass tmpClient = (ClientSocketClass)asyn.AsyncState;
        try
        {
            // END THE BeginReceive() ASYNCHRONOUS CALL BY CALLING THE EndReceive() METHOD FOR THAT SOCKET
            // THIS WILL RETURN THE NUMBER OF CHARACTER WHICH HAS BEEN RECEIVED BY THE CLIENT
            int byteMessage = tmpClient.Socket.EndReceive(asyn);

            // READ THE CONTENT
            string tmpContent = Encoding.UTF8.GetString(tmpClient.BufferSize, 0, byteMessage);

            // CHECK IF WE HAVE REACHED THE END OF THE RECEIVED MESSAGE
            if (byteMessage <= 0)
            {
                // LEAVE THE LOOP
                return;
            }

            // START WAITING AGAIN FOR NEW DATA FROM THE CLIENT
            WaitForData(tmpClient);


            // PROCESS THE CURRENT MESSAGE
            string tempData = tmpContent.Replace("\0", string.Empty);

            // LOG THE RECEPTION OF NEW DATA
            string log = string.Format("{0}{1}Received: {2}", DateTime.Now.ToString("HH:mm:ss.fff"), "\t", tempData);
            Log(LoggingType.Data, LoggingLevel.Debug, log);


            // ADD THE MESSAGE TO THE MESSAGE QUEUE
            if (MessageQueue != null)
            {
                if (tempData != null && tempData != string.Empty)
                {
                    MessageQueue.Add(tempData);
                }
            }
        }
        catch (ObjectDisposedException)
        {
            // THIS CODE WILL BE EXECUTED IF THE SOCKET WAS DISCONNECTED
            if (tmpClient != null)
            {
                // GET THE ID OF THE CLIENT
                int clientId = tmpClient.Id;

                // REMOVE THE CLIENT FROM THE CONNECTED CLIENTS LISTS
                removeClient(clientId);

                string log = string.Format("{0}{1}Client {2} disconnected", DateTime.Now.ToString("HH:mm:ss.fff"), "\t", clientId);
                Log(LoggingType.Status, LoggingLevel.Notification, log);
            }

            return;
        }            
    }