不是在c# WP8套接字中接收的全部数据

本文关键字:全部 数据 套接字 WP8 | 更新日期: 2023-09-27 18:12:55

下面的代码是完美的工作,当我收到"小"数据。但当我试图接收大数据时,它总是被切断。我收到的数据不是完整的

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

我试图增加TIMEOUT_MILLISECONDS的值和MAX_BUFFER_SIZE的大小,但没有任何变化。我需要能够获得更大的数据。我必须使用这种方式,我不能使用WebClient或HttpWebRequest…

不是在c# WP8套接字中接收的全部数据

如果你没有收到你想要的所有数据,只需再次调用接收函数。

而且,这一点非常重要,在你实现TCP之上的任何东西之前,文档你正在使用的协议,除非你实现的协议已经有文档。阅读一些基于TCP的协议文档可能会有帮助,比如SMTP、IRC、HTTP等等。

您不能指望在一个套接字中读取所有数据。您必须放入一个循环,它将继续接收数据,直到没有更多的数据可接收。

那么,你怎么知道你什么时候收到了所有的数据呢?你有几个选择:你可以发送一个分隔符字节,它只会出现在消息的末尾;如果您看到这是接收到的最后一个字节,那么就完成了。否则,您可以在消息的开头发送消息的长度(顺便说一句,这就是HTTP所做的)。或者您可以让发送方在消息完成时关闭套接字,并继续读取,直到套接字上出现EOF条件。

问题是接收调用将只读取接收数据包大小和您用于读取的缓冲区之间的最小长度。我怀疑您发送的数据太大,被系统分割成更小的数据包(称为碎片)。

我将前缀任何你发送一个整数(4字节,数据的大小来),读取它在接收端和读取字节从套接字,只要你没有收到你作为一个头发送的长度。

编辑:既然你可以使用TcpClient,我建议使用这个和.GetStream()。告诉我,如果我错了,但这个程序应该发送和接收字符串只(根据你的代码)。下面是我要做的:

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

你可以这样使用:

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
}

注意:如果您以换行符结束所有消息,则此代码有效。它也只适用于只希望传输字符串的情况(如上所述,我假设)。