是否有更好的方法在套接字上发送int列表?

时间:2015-03-17 13:48:24

标签: c# sockets serialization asynchronous deserialization

我想通过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));
}

有更好的方式/更快的方法吗?

2 个答案:

答案 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);
}