有没有更好的方法通过套接字发送 int 列表?

is there a better way of sending a list of int over a socket?

我想通过 tcp 发送一个整数列表(可以是 10 到 1000 个整数)

我确实向客户端发送了在解析数据之前它应该接收多少字节。

我也使用 BeginSend / BeginReceive 模式(每个线程一个)。

我想出了这个简单的代码来做我想做的事

const int sizeOfInt = sizeof(int);
int index = 0;

var OriginalList = new List<int>();
OriginalList.Add(1);
OriginalList.Add(42);
//.....
OriginalList.Add(9001);


//prepare and send the ArrayOfByte over the wire
var ArrayOfByte = new byte[OriginalList.Count * sizeOfInt];

foreach (var item in OriginalList)
{
    Array.Copy(BitConverter.GetBytes(item), 0, ArrayOfByte, index, sizeOfInt);

    index += sizeOfInt;
}
//socket.BeginSend(ArrayOfByte....


//socket.BeginReceive(ArrayOfByte....
//On receive move it into a List<int>
int length = ArrayOfByte.Length;

var CopyOfList = new List<int>(length / sizeOfInt);

for (index = 0; index < length; index += sizeOfInt)
{
    CopyOfList.Add(BitConverter.ToInt32(ArrayOfByte, index));
}

有更好/更快的方法吗?

更快:可能不会(您可以优化发送以匹配网络数据包大小,但这不会给您带来太大好处)。异步执行所有操作会使用更少的系统资源(不会阻塞线程),但同样不会更快。

更好:首先告诉另一端您要发送多少数据(一个单独的进程,即使在同一台机器上也无法从发送方访问 ArrayOfByte 以调整接收大小);其次将事情分解成单独的功能,每个功能都有一个目的。

想法:

创建了很多 不必要的小 byte[] 实例来收集;这是BitConverterAPI的的痛苦,但它是可以避免的;我可能只是使用位操作(shift / and)来写入字节,因为这避免了 CPU-endianness 问题,但它也可以用 unsafe 非常有效地完成; BinaryWriter 也可以

CPU 字节顺序

您实际上不需要 byte[] 来获取所有内容;您可以按顺序编写,但请注意,如果您禁用了套接字缓冲(NoDelay 等),您可能需要考虑什么是数据包合理大小[=18] =]

如果您知道有关可能的整数的更多信息,则可能会有更有效的表示形式 - 例如,"varint" 编码(基本上,类似于 UTF-8 如何以单字节编码低位字符,并使用多字节-字节为高位字符)

为了消费者有效地处理数据,您还应该发送元素的数量或元素的有效负载大小,以便接收方知道何时收到逻辑帧 - 除非只有一条消息在插座


一些基于位操作的套接字代码示例:

int index = 0;
foreach(var val in list) {
    buffer[index++] = (byte)val;
    buffer[index++] = (byte)(val >> 8);
    buffer[index++] = (byte)(val >> 16);
    buffer[index++] = (byte)(val >> 24);

    if(index == buffer.Length) { // flush buffer
        socket.Write(buffer, 0, index);
        index = 0;
    }
}
if(index != 0) { // final flush
    socket.Write(buffer, 0, index);
}

读取代码在开始前需要保证有一些整数值,则:

while(index < availableBytes) {
    int val = buffer[index++] | (buffer[index++] << 8)
            | (buffer[index++] << 16) | (buffer[index++] << 24);
    list.Add(val);
}