最有效的方法来整合通过异步网络接收的多个字节数组?

时间:2017-04-18 14:07:14

标签: c# sockets

基本上,我要做的是找到一种有效的方法来整合大量的数据,这些数据对于合适的缓冲区大小来说太大了。

对于类似即时消息设置的东西,固定缓冲区大小是一个很好的解决方案,因为大多数人都接受即时消息往往有限制。

但是,如果我想要将多个页面的整个文本文档发送出去,则您不希望一次发送2048个字符。或者无论你定义什么限制。

我在一些伪代码中表示了我当前的解决方案:

(.*)news\\(.*)

基本上这样做是为每个数据包分配一个标识符,以便它们可以使用AsyncEventArgs,因为可能不一定都会被接收而不会被中断,所以我不能真正依赖索引。

然后将它们存储在对象'DataHandler'中并合并为单个字节数组。

问题是,正如你所知,它会增加我希望成为高性能套接字服务器的大量开销。即使我要将处理程序对象集中在一起,整个事情也会让人觉得很狡猾。

编辑:它还需要一个我真的不想使用的分隔符。

那么,实现这一目标的最有效方法是什么?

编辑:处理数据的方法的示例代码,这来自其中一个异步代码项目。

from matplotlib import rc
rc('text', usetex=True)
rc('font', family='serif')

这是填充引用的用户令牌数据。

public class Pseudo
{
    public const int m_BufferSize = 255;

    public void SendAllData(Socket socket, byte[] data)
    {
        int byteCount = data.Length;

        if (byteCount <= m_BufferSize)
        {
            Socket.Send(data);
        }

        else if (byteCount > m_BufferSize)
        {
            int wholeSegments = Math.Floor(byteCount / m_BufferSize);
            int remainingBytes = byteCount % m_BufferSize;
            int bytesSent = 0;
            int currentSegment = 1;

            string id = Guid.NewGuid();

            byte[] tempData = data;

            //Send initial packet creating the data handler object.
            Socket.SendInitial(id);

            while (bytesSent < byteCount)
            {
                if (currentSegment <= wholeSegments)
                {
                    Socket.Send(tempData[m_BufferSize]);
                    tempData.CopyTo(tempData, m_BufferSize);
                    bytesSent += m_BufferSize;
                }

                else
                {
                    Socket.Send(tempData[remainingBytes]);
                    bytesSent += remainingBytes;
                }

                currentSegment++;
            }

            //Let The Server Know Send Is Over And To Consolidate;
            Socket.SendClose(id);

        }
    }

    internal class DataHandler
    {
        string m_Identity;
        List<byte[]> m_DataSegments = new List<byte[]>();

        static Dictionary<string, DataHandler> 
            m_HandlerPool = new Dictionary<string, DataHandler>();

        public DataHandler(string id)
        {
            m_Identity = id;

            if (!m_HandlerPool.ContainsKey(id))
            {
                m_HandlerPool.Add(this);
            }
        }

        public void AddDataSegment(byte[] segment)
        {
            m_DataSegments.Add(segment);
        }

        public byte[] Consolidate(string id)
        {
            var handler = m_HandlerPool(id);
            List<byte> temp = new List<byte[]>();

            for (int i = handler.m_DataSegments.Length; i >= 0; i--)
            {
                temp.Add(handler.m_DataSegments[i]);
            }

            Dispose();
            return temp;
        }

        void Dispose()
        {
            m_DataSegments = null;
            m_HandlerPool.Remove(this);
        }
    }
}

2 个答案:

答案 0 :(得分:1)

我假设您正在使用TCP / IP - 如果是这样,我就不会理解您尝试修复的问题。只要连接稳定,您就可以继续发送数据。在引擎盖下,TCP / IP将自动为您创建编号的数据包,并确保它们按照发送的顺序到达。

在接收端,您必须读取一定大小的缓冲区,但如果您打算存储数据,您可以立即将收到的数据写入MemoryStream(或FileStream在磁盘上。)

答案 1 :(得分:0)

通常是高性能服务器:

  • 使用异步发送/接收方法
  • 不要将所有收到的数据存储在内存中(如果要存储许多数据,请使用某些blob存储服务)
  • 如果需要,可以在一些可重复使用的上下文中存储一些无序的部分,并尽快将其重新发送到存储
  • 重用缓冲区,不要在每个接收/发送操作上分配新缓冲区
  • 等...