我想通过tcp
发送一个int列表(可以是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));
}
有更好的方式/更快的方法吗?
答案 0 :(得分:2)
更快:可能不是(您可以优化您的发送以匹配网络数据包大小,但这不会让您获得更多)。异步执行所有操作会占用较少的系统资源(不会阻塞线程),但同样不会更快。
更好:开始告诉另一端你要发送多少数据(一个单独的进程,即使在同一台机器上也无法从发送方访问ArrayOfByte
以确定接收的大小;第二,将各个功能分解为单独的功能。
答案 1 :(得分:2)
想法:
创建一个 lot 的不必要的小byte[]
个实例来收集;这是来自BitConverter
API的痛苦的位,但可以避免;我可能只是使用bit-ops(shift /和)来写入字节,因为这可以避免CPU端点问题,但也可以非常有效地使用unsafe
; BinaryWriter
也可以使用
CPU endianness
对于所有内容,您实际上并不需要byte[]
;您可以按顺序编写,但请注意,如果禁用了套接字缓冲(NoDelay
等),您可能需要考虑数据包的合理大小
如果你知道有关可能整数的更多信息,可能会有更高效的表示 - 例如,“varint”编码(基本上,类似于UTF-8如何在单个字节中编码低字符,并使用多字节表示高字符)
对于消费者有效处理数据,您还应该发送元素的数量或元素的有效负载大小,以便接收者知道何时接收到逻辑帧 - 除非套接字上只有一条消息< / p>
一些基于位操作的插槽代码示例:
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);
}