相当于c#异步套接字中的Peek

本文关键字:Peek 套接字 异步 相当于 | 更新日期: 2023-09-27 17:54:57

我习惯使用同步套接字。为了处理尚未完全到达的消息,我将前4个字节设置为消息的预期长度。然后我将使用Socket.Receive(tcpRecv, 1024, SocketFlags.Peek);来查看消息,而不将其从缓冲区中拉出。如果所有的东西都在那里,我就会调出数据。如果不是,我就把它留在那里。我已经设计了我的协议,使得任何消息都不会超过1024字节。

在异步套接字中,我看不到窥视数据的方法。有办法做到这一点吗?有比偷看数据更好的方法吗?

谢谢。

尼克

相当于c#异步套接字中的Peek

你不需要偷看:. net异步套接字允许你在不偷看的情况下实现相同类型的功能。我想你可能在找这样的东西:

private void BeginReceive()
{
    if ( _clientState == EClientState.Receiving)
    {
        if (_asyncTask.BytesReceived != 0 && _asyncTask.TotalBytesReceived <= _maxPageSize)
        {
            SocketAsyncEventArgs e = new SocketAsyncEventArgs();
            e.SetBuffer(_asyncTask.ReceiveBuffer, 0, _asyncTask.ReceiveBuffer.Length);
            e.Completed += new EventHandler<SocketAsyncEventArgs>(ReceiveCallback);
            e.UserToken = _asyncTask.Host;
            bool comletedAsync = false;
            try
            {
                comletedAsync = _socket.ReceiveAsync(e);
            }
            catch (SocketException se)
            {
                Console.WriteLine("Error receiving data from: " + _asyncTask.Host);
                Console.WriteLine("SocketException: {0} Error Code: {1}", se.Message, se.NativeErrorCode);
                ChangeState(EClientState.Failed);
            }
            if (!comletedAsync)
            {
                // The call completed synchronously so invoke the callback ourselves
                ReceiveCallback(this, e);
            }
        }
        else
        {
            //Console.WriteLine("Num bytes received: " + _asyncTask.TotalBytesReceived);
            ChangeState(EClientState.ReceiveDone);
        }
    }
}

当你得到回调,你可以安排另一个接收:

private void ReceiveCallback(object sender, SocketAsyncEventArgs args)
{
    lock (_sync) // re-entrant lock
    {
        // Fast fail: should not be receiving data if the client
        // is not in a receiving state.
        if (_clientState == EClientState.Receiving)
        {
            String host = (String)args.UserToken;
            if (_asyncTask.Host == host && args.SocketError == SocketError.Success)
            {
                try
                {
                    Encoding encoding = Encoding.ASCII;
                    _asyncTask.BytesReceived = args.BytesTransferred;
                    _asyncTask.TotalBytesReceived += _asyncTask.BytesReceived;
                    _asyncTask.DocSource += encoding.GetString(_asyncTask.ReceiveBuffer, 0, _asyncTask.BytesReceived);
                    BeginReceive();
                }
                catch (SocketException e)
                {
                    Console.WriteLine("Error receiving data from: " + host);
                    Console.WriteLine("SocketException: {0} Error Code: {1}", e.Message, e.NativeErrorCode);
                    ChangeState(EClientState.Failed);
                }
            }
            else if (_asyncTask.Host != host)
            {
                Console.WriteLine("Warning: received a callback for {0}, but the client is currently working on {1}.",
                    host, _asyncTask.Host);
            }
            else
            {
                Console.WriteLine("Socket Error: {0} when receiving from {1}",
                   args.SocketError,
                   _asyncTask.Host);
                ChangeState(EClientState.Failed);
            }
        }
    }
}

您可以在我的博客上看到整个异步客户端:http://codesprout.blogspot.com/2011/04/asynchronous-http-client.html

相同的数据流无需窥视即可工作:

  • 调度一个四字节的读取
  • 完成后,将其保存在缓冲区中并解码为长度"n"
  • 调度一个长度为"n"- 4的读取
  • 完成后,将其附加到已经存在的四个字节
  • 解码你的信息

与窥视的唯一区别是,您必须在最初读取它们时保存四个字节。