0

我在 C 中遇到了 Socket 的问题。数据包大小设置为3072in sock 选项,如下所示:

int         recvBuff = 3072;
int         recvLowAt = 2;

if (setsockopt(sock, SOL_SOCKET, SO_RCVLOWAT, &recvLowAt, sizeof(recvLowAt)) < 0) {
    LOGE("Error setsockopt rcvlowat -> %s\n", strerror(errno));
    close(sock);
    return -1;
}

if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &recvBuff, sizeof(recvBuff)) < 0) {
    LOGE("Error setsockopt rcvbuf -> %s\n", strerror(errno));
    close(sock);
    return -1;
}

有时数据包是< 3072,我想得到它,即使它小于3072

if ((size = recv(sock, buffer, BUFF_SIZE, 0)) < 0) {
    LOGE("Error recv -> %s\n", strerror(errno));
    size = 0;
} else {
    LOGI("%d bytes received\n", size);
}

输出是:

1448 bytes received
2896 bytes received
1448 bytes received

我想要这样的输出:

Output is :

3072 bytes received
3072 bytes received
3072 bytes received
500 bytes received
Whole data has been sended !

我试图MSG_WAITALL用作标志,recv但最后一个数据包没有发送......

我可以帮忙吗?谢谢!

4

3 回答 3

0

socket recv 调用并不总是返回发送者在其发送调用中发送的全部数据。您需要继续调用 recv 并检查是否从长度或数据内容中获取完整数据

于 2017-05-04T11:37:31.577 回答
0

需要完全填充缓冲区是一种罕见的情况,通常不需要在内核端实现。要在用户空间中实现它,您可以简单地将这段代码添加到您的代码中(它只有三行代码!!!):

unsigned char buffer[SIZE_OF_BUFFER]; /* this is the buffer */
int n, /* auxiliary variable */
    bsz = 0; /* <-- actual buffer size */

/* just loop reading until the whole buffer is full of data, or EOF or ERROR */
while (bsz < sizeof buffer && 
       (n = recv(socket, buffer + bsz, sizeof buffer - bsz, flags)) > 0)
    bsz += n; /* see NOTE */

/* here, (bsz >= sizeof buffer) || (n <= 0), ==> BUFFER FULL, EOF in socket, or some other error happened */
if (n < 0) { 
    /* process error command */
} else if (n == 0) { 
    /* process EOF in connection */
} else {
    /* process a completely filled buffer */
}

这也可以实现为for循环:

for(bsz = 0;
    bsz < sizeof buffer &&
    (n = recv(socket, buffer + bsz, sizeof buffer - bsz, flags)) > 0;
    bsz += n) continue;  /* used continue; as only ; for an empty loop body is weird */

笔记

好吧,断言(bsz >= sizeof buffer)实际上更具限制性,并且可以写成(bsz == sizeof buffer)系统recv调用始终保证返回值小于或等于请求的字节数。这导致在执行循环体之后,new_bsz <= old_bsz + (sizeof buffer - old_bsz)new_bsz <= sizeof buffer. 所以最后,这两个断言都是真的(bsz >= sizeof bufferbsz <= sizeof buffer,这意味着bsz == sizeof buffer)。量子点

于 2017-05-05T07:10:43.097 回答
0

即使低于 3072 我也想得到它

你会。

我想要这样的输出

你不会的。TCP 没有义务在阻塞模式下一次传输超过一个字节。如果您一次想要 3072(或其他)字节,则必须循环。

NB 引用的两个陈述是相互矛盾的。

于 2017-05-04T11:41:00.147 回答