【问题标题】:How async Socket.EndReceive know the number of bytes it read? And how does async socket finish reading?async Socket.EndReceive 如何知道它读取的字节数?以及异步套接字如何完成读取?
【发布时间】:2014-05-14 09:10:43
【问题描述】:

我有这个代码

_socket.BeginReceive(
        _buffer, 
        0, 
        _buffer.Length, 
        SocketFlags.None, 
        _asyncCallback, 
        sSocketName);

**with**
_buffer.Length = 262144;
_asyncCallback = OnReceive;
sSocketName is a state string object (sSocketName = "History")

还有 AsynCallback 委托方法:

private void OnReceive(IAsyncResult asyn)
{
    if (asyn.AsyncState.ToString().Equals("History"))
    {
       int receivedBytes = _socket.EndReceive(asyn);
       string data = Encoding.ASCII.GetString(_buffer, 0, receivedBytes);
       //...
    }
    //...
}

receivedBytes 是一个整数,表示接收到的字节数。就我而言,大约是 23,000 -> 25,000。

套接字服务器是一个互联网服务器,它以字符串消息的形式不断将原始数据推送到我的客户端套接字,它有超过 25,000 字节的数据。

所以我的问题:

  1. 什么决定了接收的字节数?
  2. 什么决定接收是否完成?

【问题讨论】:

    标签: c# sockets asynchronous asyncsocket


    【解决方案1】:

    发送“完成”消息时不一定会触发异步回调。它读取尽可能多的字节。只有您可以确定是否已收到所有数据。因此,如果您发送字符串“Hello World”,则在一个回调中首先接收“Hell”,然后在下一个回调中接收“o World”,这是一个完全有效的场景。

    您必须自己确定消息的长度,方法是滚动您自己的协议,例如通过在您发送的消息前面加上要发送的数据长度。

    作为一个简单的例子,假设 chars 是 1 字节,最大消息长度是 255,并且您想要发送 1 字节字符的字符串。您需要做的是保持“阅读器状态”,这样您就可以跟踪您在阅读消息时所处的位置,而不是假设它会是所有内容。这是一个非常粗略的代码示例,但我希望你明白我的意思。

    private enum State
    {
       MessageLength
       MessageData
    }
    
    private State _state;
    private void OnEndReceive(IAsyncCallback ia)
    {
        int bytesRead = _socket.EndReceive(ia);
    
    
        if (_state == MessageLength) 
        {
            // read and store the message length byte
        }
        else if (_state == State.MessageData)
        {
            // read message data up to the number of bytes received .
            // if there's data left to be read for the current message, read it.
            // if more bytes have been received than there is message data, it means there's a 
            // new message already waiting
        }
    
    }
    

    【讨论】:

    • 在您的示例中,您是说“Hell”是由确定发送的,这意味着您可以决定先从服务器套接字发送“Hell”,然后再发送“o World”?跨度>
    • 不,我的意思是说,无论你一次性发送,不一定会一次性收到
    • 是的,谢谢,但是否有可能知道为什么收到“Hell”而不收到“Hello”?
    • 除非连接失败或套接字错误,所有内容都将在某一时刻收到。只是没有什么要求它成为第一个回调中的所有内容。您无法控制什么多少,但是
    猜你喜欢
    • 2011-05-07
    • 1970-01-01
    • 1970-01-01
    • 2016-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-01
    相关资源
    最近更新 更多