设置套接字recv缓冲区大小没有块

时间:2017-05-04 11:25:34

标签: c sockets recv setsockopt

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

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作为标记,但最后一个数据包未被发送...

我可以帮忙吗? 谢谢!

3 个答案:

答案 0 :(得分:0)

套接字recv调用并不总是返回发送方在其发送调用中发送的所有数据。 如果你有完整的数据,你需要继续调用recv并检查长度或数据内容

答案 1 :(得分:0)

  

即使它不到3072,我也希望得到它

你会。

  

我想要像这样的输出

你没赢。在阻塞模式下,TCP不必一次传输多个字节。如果您想同时使用3072(或其他)字节,则必须循环。

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

答案 2 :(得分: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)。的 QED