Sockets 当我请求的数据超过当前可用数据量时,`recv`是否会阻塞TCP套接字?

Sockets 当我请求的数据超过当前可用数据量时,`recv`是否会阻塞TCP套接字?,sockets,tcp,recv,Sockets,Tcp,Recv,TCP可以任意合并和拆分数据包。因此,假设我这样做,例如,这样一个电话: `recv(sock, buf, 15, 0)` 但目前只有5个字节的数据可立即使用—— recv()会一直阻塞到15字节的数据可用,还是我只会得到5字节 我这样问是因为我想知道我是否可以这样简单地读取uint32\u t(假设I是uint32\u t类型的变量): 后者显然更加丑陋和艰巨,但不幸的是,如果在包被拆分的情况下,recv()在收到所有请求的数据之前都不阻塞,则后者是必需的。通常,没有设置任何特殊标志、套接字

TCP可以任意合并和拆分数据包。因此,假设我这样做,例如,这样一个电话:

`recv(sock, buf, 15, 0)`
但目前只有
5个字节的数据可立即使用——

recv()
会一直阻塞到
15
字节的数据可用,还是我只会得到
5
字节

我这样问是因为我想知道我是否可以这样简单地读取
uint32\u t
(假设
I
uint32\u t
类型的变量):


后者显然更加丑陋和艰巨,但不幸的是,如果在包被拆分的情况下,
recv()
在收到所有请求的数据之前都不阻塞,则后者是必需的。

通常,没有设置任何特殊标志、套接字选项或IOCTL,对阻塞TCP套接字的
recv
调用将返回小于或等于所请求大小的任何字节数。但除非套接字远程关闭、被信号中断或处于错误状态,否则它将阻塞,直到至少有1个字节可用

换句话说,如果您请求15个字节,但只有5个可用,
recv
将返回5

应用程序开发人员不应依赖于数据的发送或构造方式,而应将其套接字视为能够随时返回部分数据流。(或者,正如我告诉其他人的那样,编写代码时就好像
recv
一次只返回1个字节一样)

接收数据的常见循环通常如下所示。注意recv调用中在
缓冲区上完成的指针数学运算

unsigned char buffer[bytes_expected];
ssize_t bytes_received = 0;
while (bytes_received < bytes_expected)
{
    int result = recv(sock, buffer + bytes_received, bytes_expected-bytes_received, 0);
    if (result == 0)
    {
        // socket was closed remotely - break out of the loop
    }
    else if (result < 0)
    {
        // socket was closed on remote end or hit an error
        // either way, the socket is likely dead
        break;
    }
    else
    {
        bytes_received += result;
    }
}
无符号字符缓冲区[预期字节];
ssize_t bytes_received=0;
while(接收字节数<预期字节数)
{
int result=recv(sock,buffer+bytes\u received,bytes\u expected-bytes\u received,0);
如果(结果==0)
{
//插座远程关闭-断开回路
}
否则如果(结果<0)
{
//套接字在远程端关闭或遇到错误
//不管是哪种情况,插座都可能死了
打破
}
其他的
{
字节_接收+=结果;
}
}
我所知道的这个规则的例外是
MSG_WAITALL
标志,它是
recv
的最后一个参数。它将保持套接字(块),直到您获得传递给
recv
length
参数所请求的所有字节为止(或直到错误或套接字关闭为止)

从:

MSG_WAITALL(自Linux 2.2以来)此标志请求 阻止,直到满足完整请求。然而,这一呼吁可能仍然存在 如果捕获到信号、错误或错误,则返回的数据少于请求的数据 发生断开连接,或者下一个要接收的数据是不同的 输入的值大于返回的值


事实上,你甚至被问到这个问题,这让你比其他大多数刚接触插座的人都有优势。现实世界中存在如此多的错误代码,因为大多数开发人员没有处理recv返回的内容低于预期的情况。

通常,在没有设置任何特殊标志、套接字选项或IOCTL的情况下,对阻塞TCP套接字的
recv
调用将返回小于或等于所请求大小的任何字节数。但除非套接字远程关闭、被信号中断或处于错误状态,否则它将阻塞,直到至少有1个字节可用

换句话说,如果您请求15个字节,但只有5个可用,
recv
将返回5

应用程序开发人员不应依赖于数据的发送或构造方式,而应将其套接字视为能够随时返回部分数据流。(或者,正如我告诉其他人的那样,编写代码时就好像
recv
一次只返回1个字节一样)

接收数据的常见循环通常如下所示。注意recv调用中在
缓冲区上完成的指针数学运算

unsigned char buffer[bytes_expected];
ssize_t bytes_received = 0;
while (bytes_received < bytes_expected)
{
    int result = recv(sock, buffer + bytes_received, bytes_expected-bytes_received, 0);
    if (result == 0)
    {
        // socket was closed remotely - break out of the loop
    }
    else if (result < 0)
    {
        // socket was closed on remote end or hit an error
        // either way, the socket is likely dead
        break;
    }
    else
    {
        bytes_received += result;
    }
}
无符号字符缓冲区[预期字节];
ssize_t bytes_received=0;
while(接收字节数<预期字节数)
{
int result=recv(sock,buffer+bytes\u received,bytes\u expected-bytes\u received,0);
如果(结果==0)
{
//插座远程关闭-断开回路
}
否则如果(结果<0)
{
//套接字在远程端关闭或遇到错误
//不管是哪种情况,插座都可能死了
打破
}
其他的
{
字节_接收+=结果;
}
}
我所知道的这个规则的例外是
MSG_WAITALL
标志,它是
recv
的最后一个参数。它将保持套接字(块),直到您获得传递给
recv
length
参数所请求的所有字节为止(或直到错误或套接字关闭为止)

从:

MSG_WAITALL(自Linux 2.2以来)此标志请求 阻止,直到满足完整请求。然而,这一呼吁可能仍然存在 如果捕获到信号、错误或错误,则返回的数据少于请求的数据 发生断开连接,或者下一个要接收的数据是不同的 输入的值大于返回的值


事实上,你甚至被问到这个问题,这让你比其他大多数刚接触插座的人都有优势。现实世界中存在如此多的错误代码,因为大多数开发人员都没有处理recv返回的内容低于预期的情况。

谢谢。因此,我的第二段代码的丑陋和艰辛是无法逃避的?
MSG_WAITALL
可能满足您的需要。您的代码片段中有一个bug(您没有对问题中的
buff
进行指针计算)。请参阅我提供的代码示例。谢谢。因此,我的第二段代码的丑陋和艰辛是无法逃避的?
MSG_WAITALL
可能满足您的需要。您的代码片段中有一个bug(您没有对问题中的
buff
进行指针计算)。请参阅我提供的代码示例。
unsigned char buffer[bytes_expected];
ssize_t bytes_received = 0;
while (bytes_received < bytes_expected)
{
    int result = recv(sock, buffer + bytes_received, bytes_expected-bytes_received, 0);
    if (result == 0)
    {
        // socket was closed remotely - break out of the loop
    }
    else if (result < 0)
    {
        // socket was closed on remote end or hit an error
        // either way, the socket is likely dead
        break;
    }
    else
    {
        bytes_received += result;
    }
}