C# SocketAsyncEventArgs 处理接收和发送数据 [英] C# SocketAsyncEventArgs handling receive and send data

查看:28
本文介绍了C# SocketAsyncEventArgs 处理接收和发送数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to understand the 'SocketAsyncEventArgs' class in C#. http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx

我正在学习本教程:http://www.codeproject.com/Articles/83102/C-SocketAsyncEventArgs-高性能套接字编码

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

Now I am stuck into how I exactly should process data with my server. What I am trying to do is use a SocketAsyncEventArgs for a connected client with an allocated Buffer space of 512 bytes in the BufferManager. Then what I want to do is to decode the byte[] data into my own custom class (ClientPacket) which holds the byte[] for decoding and reading from.

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

This is all well but my server doesn't always respond with data the question is:

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

Do I use 1 SocketAsyncEventArgs for the receiving and loop around to process receive data, then allocate a SocketAsyncEventArgs from the pool whenever I need to send then return it on completion?

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

And how does the SocketAsyncEventArgs know when reading is complete? (when it is finished with the byte[] buffer before it over-writes it with new data) like how is it returned to the pool when done if I don't respond back?

推荐答案

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

I only use one SocketAsyncEventArgs instance for all of my needs. I simply reset the buffer between each request (by setting it to a new Byte[]).

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

Once I have connected and have a reference to the Socket, I start listening like this:

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

    socket.ReceiveAsync(e);
}

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

I have a helper function that resets the buffer:

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

    e.SetBuffer(buffer, 0, SocketBufferSize);
}

我处理数据如下:

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

    ResetBuffer(e);

    socket.ReceiveAsync(e);
}

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

In ProcessData, you can use the byte array as needed to pull in the data. I use it to create a MemoryStream which I then deserialize into my class (similar to ClientPacket), as follows:

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

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

As for your last question. The framework handles everything to do with the underlying TCP protocol, etc. so you can rely on the event handler being called whenever there is data to be processed. Use the e.BytesTransferred value to indicate the amount of data you actually received which may be smaller than but will never exceed your buffer size (SocketBufferSize in my code). If the message was larger than the buffer size, the TCP infrastructure will buffer the messages and send them to you in chunks based on SocketBufferSize (by raising the event once for each chunk). If this is a concern, simply increase SocketBufferSize until the majority of your message are received in one chunk.

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

The downside of the chunking is that messages may be merged by the infrastructure which means that you may need a way to tell when the first message has ended. Typical approaches include prefacing your message with a 4 byte integer that indicates the message length. I can elaborate more if needed.

希望有所帮助.

这篇关于C# SocketAsyncEventArgs 处理接收和发送数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆