有没有更好的方法通过套接字发送 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[]
实例来收集;这是BitConverter
API的位的痛苦,但它是可以避免的;我可能只是使用位操作(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);
}
我想通过 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[]
实例来收集;这是BitConverter
API的位的痛苦,但它是可以避免的;我可能只是使用位操作(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);
}