简体   繁体   English

套接字C#WP8中未收到全部数据

[英]Not the whole data received in a socket C# WP8

The code below is perfectly working when i receive "small" data. 当我收到“小”数据时,下面的代码可以正常工作。 But when i try to receive a big data , it always cut. 但是,当我尝试接收大数据时,它总是会中断。 The data that i received isn't whole 我收到的数据不完整

static ManualResetEvent _clientDone = new ManualResetEvent(false);

        const int TIMEOUT_MILLISECONDS = 500000000;

        const int MAX_BUFFER_SIZE = 2048;

 public string Receive_msg()
        {
            string response = "Operation Timeout";

            if (_socket != null)
            {
                SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
                socketEventArg.RemoteEndPoint = _socket.RemoteEndPoint;

                socketEventArg.SetBuffer(new Byte[MAX_BUFFER_SIZE], 0, MAX_BUFFER_SIZE);


                socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
                {
                    if (e.SocketError == SocketError.Success)
                    {
                        response = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
                        response = response.Trim('\0');
                        Debug.WriteLine(response);
                    }
                    else
                    {
                        response = e.SocketError.ToString();
                    }

                    _clientDone.Set();
                });

                _clientDone.Reset();

                _socket.ReceiveAsync(socketEventArg);

                _clientDone.WaitOne(TIMEOUT_MILLISECONDS);
            }
            else
            {
                response = "Socket is not initialized";
            }
            return response;
        }

I tried to increase the value of the TIMEOUT_MILLISECONDS and the size of my MAX_BUFFER_SIZE , but nothing change. 我试图增加TIMEOUT_MILLISECONDS的值和MAX_BUFFER_SIZE的大小,但没有任何改变。 I need to be able to get a bigger data. 我需要能够获得更大的数据。 And i must use this way, i can't use WebClient or HttpWebRequest... 而且我必须使用这种方式,我不能使用WebClient或HttpWebRequest ...

If you didn't receive all the data you want, just call your receive function again. 如果您没有收到所有想要的数据,只需再次调用您的接收函数。

Also, and this very important, before you implement anything on top of TCP, document the protocol you're using unless you're implementing a protocol that's already documented. 同样,这一点非常重要,除非您要实现已经记录的协议,否则在实现TCP之上的任何东西之前,都要记录正在使用的协议。 It may be helpful to read the protocol documentation for some protocol layered on top of TCP such as SMTP, IRC, HTTP, or the like. 阅读位于TCP之上的某些协议(例如SMTP,IRC,HTTP等)的协议文档可能会有所帮助。

You can't count on getting all your data in a single socket read. 您不能指望在单个套接字中读取所有数据。 You have to put in a loop that will continue to receive data until there is no more data to receive. 您必须放入一个循环,它将继续接收数据,直到没有更多数据要接收为止。

How, then, do you tell when you have received all your data? 那么,如何知道何时收到所有数据? You have a couple of options: you can send a delimiter byte that will only appear at the end of the message; 您有两种选择:您可以发送一个定界符字节,该定界符字节仅出现在消息的末尾。 if you see that as the last byte received you are done. 如果您看到接收到的最后一个字节已完成。 Otherwise, you can send the length of the message at the start of the message (this is what HTTP does, btw). 否则,您可以在消息的开头发送消息的长度(这就是HTTP所做的,顺便说一句)。 Or you can have the sender close the socket when the message is complete, and just keep reading until there is an EOF condition on the socket. 或者,您可以让发件人在消息完成后关闭套接字,然后继续阅读直到套接字上出现EOF状况为止。

The thing is that the receive call will only read the minimum length between the receiving packet size and the buffer you use for reading. 事实是,接收调用只会读取接收数据包大小和您用于读取的缓冲区之间的最小长度。 I suspect the data you send to be too large and getting split by the system into smaller packets (called fragmentation). 我怀疑您发送的数据太大,并且被系统分割成较小的数据包(称为碎片)。

I would prefix anything you send with an integer (4 bytes, the size of the data to come), read it on the receiving side and read bytes from the socket as long as you haven't received the length you sent as a header. 只要您没有收到作为标头发送的长度,我都会为您发送的任何内容加上一个整数(4个字节,即将到来的数据大小),在接收端读取它并从套接字读取字节。

Edit: Since you can use TcpClient, I would recommend using this and the .GetStream() . 编辑:因为您可以使用TcpClient,我建议使用此和.GetStream() Tell me if i'm wrong, but this program should send and receive strings only (according to your code). 告诉我我是否错,但是此程序应仅发送和接收字符串(根据您的代码)。 Here's what I would do: 这就是我要做的:

public async Task<string> ReceiveString()
{
    NetworkStream netStream = _client.GetStream(); //Using _client instead of _socket
    StreamReader streamReader = new StreamReader(netStream);
    string result = await streamReader.ReadLine(); //Reading the stream until we find a newline
    return result;
}

And you would use it like so: 您将像这样使用它:

void MyMethod()
{
    string message = await ReceiveString(); //This is the fully async way, the "MyMethod" signature should be "async void" too in order to use "await"

    string message = ReceiveString().Result; //This is a blocking call, waits for everything to be received before proceding
}

Note: This code works if you end all your messages with a newline character. 注意:如果您用换行符结束所有消息,则此代码有效。 It also only applies if you only want to transfer strings (as mentioned above, I assumed). 它也仅在您只想传输字符串的情况下适用(如上所述,我假设是)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM