繁体   English   中英

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

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

当我收到“小”数据时,下面的代码可以正常工作。 但是,当我尝试接收大数据时,它总是会中断。 我收到的数据不完整

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 ...

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

同样,这一点非常重要,除非您要实现已经记录的协议,否则在实现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
}

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

暂无
暂无

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

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