C#SocketAsyncEventArgs处理接收和发送数据

8 c# sockets tcp socketasynceventargs

我试图理解C#中的'SocketAsyncEventArgs'类.http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx

我正在关注本教程:http: //www.codeproject.com/Articles/83102/C-SocketAsyncEventArgs-High-Performance-Socket-Cod

现在我陷入了我应该如何处理我的服务器数据的问题.我想要做的是使用SocketAsyncEventArgs为BufferManager中分配的512字节缓冲区空间的连接客户端.那么我想要做的是将byte []数据解码为我自己的自定义类(ClientPacket),该类保存用于解码和读取的byte [].

这一切都很好,但我的服务器并不总是回答数据问题是:

我是否使用1个SocketAsyncEventArgs进行接收并循环处理接收数据,然后在需要发送时从池中分配SocketAsyncEventArgs然后在完成时返回它?

SocketAsyncEventArgs在读取完成时如何知道?(当它在用新数据覆盖它之前完成了byte []缓冲区),如果我没有回复,它如何在完成后返回池中?

Son*_*ate 11

我只使用一个SocketAsyncEventArgs实例来满足我的所有需求.我只是在每个请求之间重置缓冲区(通过将其设置为新的Byte []).

一旦我连接并引用了Socket,我就开始这样听:

public void StartListening(SocketAsyncEventArgs e)
{
    ResetBuffer(e);
    e.Completed += SocketReceive;

    socket.ReceiveAsync(e);
}
Run Code Online (Sandbox Code Playgroud)

我有一个帮助函数重置缓冲区:

private void ResetBuffer(SocketAsyncEventArgs e)
{
    var buffer = new Byte[SocketBufferSize];

    e.SetBuffer(buffer, 0, SocketBufferSize);
}
Run Code Online (Sandbox Code Playgroud)

我处理的数据如下:

private void SocketReceive(Object sender, SocketAsyncEventArgs e)
{
    ProcessData(e.Buffer, 0, e.BytesTransferred);

    ResetBuffer(e);

    socket.ReceiveAsync(e);
}
Run Code Online (Sandbox Code Playgroud)

在ProcessData中,您可以根据需要使用字节数组来提取数据.我用它来创建一个MemoryStream然后我反序列化到我的类(类似于ClientPacket),如下所示:

private void ProcessData(Byte[] data, Int32 count)
{
    using (var stream = new MemoryStream(data, 0, count))
    {
        var serializer = new XmlSerializer(typeof(ClientPacket));

        var packet = serializer.Deserialize(stream);

        // Do something with the packet
    }
}
Run Code Online (Sandbox Code Playgroud)

至于你的上一个问题.该框架处理与底层TCP协议等有关的所有事情,因此您可以依赖于每当有数据需要处理时调用的事件处理程序.使用e.BytesTransferred值表示实际收到的数据量可能小于但不会超过缓冲区大小(我的代码中为SocketBufferSize).如果消息大于缓冲区大小,TCP基础结构将缓冲消息并基于SocketBufferSize以块的形式将它们发送给您(通过为每个块提升一次事件).如果这是一个问题,只需增加SocketBufferSize,直到在一个块中收到大部分消息.

分块的缺点是消息可能被基础结构合并,这意味着您可能需要一种方法来判断第一条消息何时结束.典型方法包括使用指示消息长度的4字节整数来表示消息.如果需要,我可以详细说明.

希望有所帮助.

  • 通过为每个 XxxAsync 调用创建一个新的 Byte[],您将销毁并创建一个新对象。减少对象的创建和垃圾回收难道不是SAEA的要点之一吗? (2认同)