如果发送的数据小于bufsize,recv(bufsize)是否保证接收所有数据



例如:

客户端

...
socket.connect(server_address)
data = some_message_less_than_100_bytes
socket.sendall(data)
...

服务器端

...
socket.accept()
socket.recv(1024)
...

服务器端是否保证在一个recv()中接收数据?

如果没有,使用标头指定消息长度的标准解决方案是如何工作的?标头本身可能已被拆分,我们必须检查标头是否已正确接收。或者页眉是固定长度的?这样,无论发送多少数据,接收器都可以以相同的方式解释前几个字节?

事实上,我正试图做一些类似的事情

客户端

while():
send()
recv()

服务器

recv()
while():
send() # Acknowledge to client
recv()

这是ravi在Linux套接字中建议的:如何让send((等待recv((

但我解决了上面描述的问题。

ravi的答案是否假设客户端和服务器都将接收到对方在单个recv((中发送的内容?

更新

我很想发布这张照片,但我不能,因为我的声誉很低。。。

以下链接是HTTP帧格式

https://datatracker.ietf.org/doc/html/rfc7540#section-4

它确实使用了一个固定长度的解决方案,因此无论头被拆分多少块,它都可以以相同的方式工作。

所以我想,某种"固定"长度是唯一的解决方案吗?即使标头大小本身是可变的,它也可能有一些承诺的位来指示标头的长度。我说得对吗?

服务器端是否保证在一个recv((中接收数据?

对于UDP,是。recv()将返回1个完整的数据报,或者返回一个错误。不过,如果缓冲区大小小于数据报,那么数据将被截断,您无法恢复它

对于TCP,没有。唯一的保证是,如果没有发生错误,那么recv()将返回至少1个字节,但不超过指定缓冲区大小,它可以返回介于两者之间的任何数量的字节。

如果不是,使用标头指定消息长度的标准解决方案是如何工作的?标头本身可能已被拆分,我们必须检查标头是否已正确接收。或者页眉是固定长度的?

它可以采用任何一种方式,具体取决于标头的特定格式。许多协议使用固定长度的报头,许多协议使用可变长度的报头。

无论哪种方式,您都可能需要多次调用send()以确保发送所有相关字节,并多次调用recv()以确保接收所有字节。TCP中的发送和读取之间没有1:1的关系。

ravi的答案是否假设客户端和服务器都将接收到对方在单个recv((中发送的内容?

Ravi的回答对send()发送和recv()接收的字节数没有任何假设。他的回答是从更高层次的角度提出的。但是,强制执行所需的行为是非常琐碎的,例如:

int sendAll(int sckt, void *data, int len)
{
char *pdata = (char*) data;
while (len > 0) {
int res = send(sckt, pdata, len, 0);
if (res > 0) {
pdata += res;
len -= res;
}
else if (errno != EINTR) {
if ((errno != EWOULDBLOCK) && (errno != EAGAIN)) {
return -1;
}
/*
optional: use select() or (e)poll to
wait for the socket to be writable ...
*/
}
}
return 0;
}
int recvAll(int sckt, void *data, int len)
{
char *pdata = (char*) data;
while (len > 0) {
int res = recv(sckt, pdata, len, 0);
if (res > 0) {
pdata += res;
len -= res;
}
else if (res == 0) {
return 0;
}
else if (errno != EINTR) {
if ((errno != EWOULDBLOCK) && (errno != EAGAIN)) {
return -1;
}
/*
optional: use select() or (e)poll to
wait for the socket to be readable ...
*/
}
}
return 1;
}

这样,您可以使用sendAll()发送消息头,然后再发送消息数据,使用recvAll()接收消息头,再发送消息数据。

服务器端是否保证在一个recv((中接收数据?

否。TCP是一个字节流,而不是一个消息协议。虽然在大多数情况下,它可能会处理小消息和空的发送缓冲区,但如果数据发送大于底层数据链路的MTU,它就会开始失败。TCP不保证任何原子发送recv对,但对于任何东西,除了单个八位字节。因此,即使是小数据也不要指望它。

相关内容

  • 没有找到相关文章

最新更新