在c#中从Socket接收数据的正确方法是什么?

时间:2017-09-29 13:29:06

标签: c# sockets tcp

假设我事先了解了有效负载字节。接收所有字节的正确方法是什么?目前,我正在做这样的事情

byte[] buffer = new byte[payloadLength];
socket.Receive(buffer, buffer.Length, SocketFlags.None);

但是,我认为如果有效负载很大并且Receive可能无法一次性接收整个数据。所以我打算做这样的事情

byte[] buffer = new byte[payloadLength];
int remained = payloadLength;
int size = 0;
do {
    size = socket.Receive(buffer, payloadLength - remained, remained, SocketFlags.None);
    remained -= size;
} while (remained > 0 && size > 0);

哪一个更正确?或者你的家伙有更好的主意吗?

2 个答案:

答案 0 :(得分:2)

绝对某些变体,如第二个。忽略Receive的返回值是SO上最常见的初学者错误之一,因为合同保证(如果你不要求0字节){ {1}}返回的是它将读取至少一个字节。它无法保证它会尝试读取您要求的字节数。 1

任何消息框架(例如此处显示固定大小的消息)都取决于在TCP字节流上实现。

1 即使接收尺寸相对较小,也无法保证。因此,如果你知道你的消息有多大,因为你首先发送长度(另一种常见的消息框架方式),你需要循环甚至获得构成消息的2/4/8字节长度短,整数或长。

答案 1 :(得分:1)

在实践中,第一种选择通常有效。但是你不能保证它,所以如果你关心的是一个严肃的程序,那么采取第二种方法。

当然,如果您切换到ReceiveAsync,如果您有高性能需求,那么您需要采用第二种方法。