当我的套接字断开连接时,为什么我要接收数据? [英] Why am I receiving data when my Socket has disconnected?

查看:63
本文介绍了当我的套接字断开连接时,为什么我要接收数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的套接字有问题.基本上,我有一些侦听器可以侦听PC上所有可用的端口.当套接字连接到其中一个侦听器时,我将打开一个新的Socket-connection来处理该连接,然后我的侦听器将返回侦听状态.

I'm having an issue with my Sockets. Basically I have a few listeners that listen on all the available ports on my pc. When a socket connects to one of the listeners, I open a new Socket-connection to handle that connection and my listener goes back to listening.

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

However when a client disconnects I keep on receiving empty data. As you can see in the code below, I have put a Console.WriteLine to check the length of the received message. When the connection closes, it's showing me well over a 100 lines with charLen: 0. Meaning it's receiving something but I don't know where it's coming from.

然后我还将在 WaitData -方法

        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方法:

Below you see the WaitForData-method:

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

现在,我开始认为在处理 OnDataReceived 中的数据时出现了问题.我一直在组合在网上找到的不同教程,以获取此代码,该代码本身是有效的,仅当客户端断开连接时,我才收到此错误.

Now I'm beginning to think that something is wrong in the way I'm handling the data in the OnDataReceived. I have been combining different tutorials I found online to get to this code, which in itself is working, only when the client disconnects I'm getting this error.

我希望有人知道原因.

为完整起见,下面将找到我用来组织连接的客户端的ClientSocketClass.

To be complete, below you will find the ClientSocketClass which I'm using to organise my connected clients.

    public class ClientSocketClass
    {
        private int tmpId;
        private string tmpIp;
        private byte[] tmpBuffer;
        public event PropertyChangedEventHandler PropertyChanged;

        public int Id
        {
            get { return tmpId; }
            set
            {
                tmpId = value;
                this.NotifyPropertyChanged("Id");
            }
        }


        public string Ip
        {
            get { return tmpIp; }
            set
            {
                tmpIp = value;
                this.NotifyPropertyChanged("Ip");
            }
        }

        [Browsable(false)]
        public Socket Socket { get; set; }

        [Browsable(false)]
        public byte[] BufferSize
        {
            get { return tmpBuffer; }
            set
            {
                tmpBuffer = value;
                this.NotifyPropertyChanged("BufferSize");
            }
        }

        private void NotifyPropertyChanged(string name)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
    }

此类在BindingList中使用,该类在DataGridView中显示以显示连接的客户端.但是我只显示了ID和IP地址,因此 [Browsable(false)]

This class is being used in a BindingList which is displayed in a DataGridView to show the connected clients. But I'm only showing the Id and the IP Address, hence the [Browsable(false)]

推荐答案

我能够在StackOverflow( https://stackoverflow.com/a/9546493/4425684 )

I was able to find the answer here on StackOverflow (https://stackoverflow.com/a/9546493/4425684)

我没有意识到的是WaitForData实际上生成了一个循环,当我收到NULL时,我需要对循环进行转义.

What I didn't realize was that WaitForData actually generated a loop and I needed to escape the loop when I was receiving NULL.

因此,只需添加以下代码,即可解决问题.

So by just adding the below code, the problem was solved.

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

我确实认为此代码仍然存在问题,因为我认为当收到大于缓冲区的消息时,由于仅在 WaitForData ,但我不确定.

I do think that there's still an issue with this code, because I think that when a message is received which is larger than my buffer, the message will not be completely parsed since I'm only processing the message after the WaitForData, but I'm not completely sure.

目前,此问题已解决,因为我的缓冲区很大,但是如果有人要纠正它,请放心.

For now the problem is solved because I have made my buffer very large, but if someone wants to correct it, please feel free.

这篇关于当我的套接字断开连接时,为什么我要接收数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆