【问题标题】:how to send and receive data chunk by chunk in linux sockets如何在linux套接字中逐块发送和接收数据
【发布时间】:2021-08-20 20:29:08
【问题描述】:

应该怎么样?

我正在尝试在服务器和客户端之间进行通信,服务器可以向客户端发送大数据,并且需要立即执行而不会被阻塞。这个数据可能是10mb-100mb 所以我想一块一块地发送但是我做不到

【问题讨论】:

  • 要发送/接收超过一个字节的消息,您需要一个基于 TCP 的协议。您还必须正确且完整地处理从系统调用(如 recv())返回的结果。
  • 您使用的是 UDP 还是 TCP 套接字?显示minimal reproducible example
  • 我使用 TCP/IP 套接字
  • 请注意 TCP 不是面向数据报的。这意味着接收方无法知道发送方发送了多少字节(除非长度在数据本身或过程中)。 send 的调用次数与 recv 的调用次数之间存在 NO 关系。
  • 发送限制没有问题。发送将被阻塞(除非您将套接字设置为非阻塞模式),直到有数据空间。 TCP 是一个“窗口”可靠协议。数据由具有 CRC 的数据包发送,并且每个数据包都必须由接收器确认。但是在发送方停止发送并等待确认之前,可以发送许多尚未确认数据包。如果缺少 ACK 或 NAK(接收方检测到数据损坏),则会重新发送数据包。

标签: c sockets


【解决方案1】:

首先,您的 2 个函数比它们需要的要复杂一些。它们可以被简化。

例如,可以删除 send_data() 中的整个 SIZELIMIT 处理,因为您直接发送 data 缓冲区,所以只需给 send()data 中一样多的字节数和让send() 告诉你它实际接受了多少字节。

但更重要的是,receive_data() 需要考虑输入 buffer 的大小。您只是盲目地阅读,对实际发送的数据量没有任何概念。您正在将一个可变长度的字符串传递给send_data(),这很容易超过receive_data() 的调用者所期望的buffer 大小。

另外,你根本没有任何错误处理。

尝试类似的方法:

int send_data(int sockfd, const void *buffer, size_t bufsize)
{
    const char *pbuffer = (const char*) buffer;
    while (bufsize > 0)
    {
        int n = send(sockfd, pbuffer, bufsize, 0);
        if (n < 0) return -1;
        pbuffer += n;
        bufsize -= n;
    }
    return 0;
}

int receive_data(int sockfd, void *buffer, size_t bufsize)
{
    char *pbuffer = (char*) buffer;
    while (bufsize > 0)
    {
        int n = recv(sockfd, pbuffer, bufsize, 0);
        if (n <= 0) return n;
        pbuffer += n;
        bufsize -= n;
    }
    return 1;
}

然后您可以在这些功能之上构建其他功能。例如,在发送字符之前将字符串的长度作为整数发送,例如:

int send_int32(int sockfd, int32_t data)
{
    data = htonl(data);
    return send_data(sockfd, &data, sizeof(data));
}

int receive_int32(int sockfd, int32_t *data)
{
    int ret = receive_data(sockfd, data, sizeof(*data));
    if (ret <= 0) *data = 0;
    else *data = ntohl(*data);
    return ret;
}

int send_str(int sockfd, const char *data)
{
    int32_t size = strlen(data);
    int ret = send_int32(sockfd, size);
    if (ret == 0) ret = send_data(sockfd, data, size);
    return ret;
}

int receive_str(int sockfd, char **data)
{
    *data = NULL;
    int32_t size;
    int ret = receive_int32(sockfd, &size);
    if (ret > 0) {
        *data = malloc(size+1);
        if (*data == NULL) return -1;
        ret = receive_data(sockfd, *data, size);
        if (ret <= 0) {
            free(*data);
            *data = NULL;
        }
        else {
            (*data)[size] = '\0';
        }
    }
    return ret;
}
send_str(sockfd, "Hello World!");
char *str;
if (receive_str(sockfd, &str) > 0) {
    ...
    free(str);
}

【讨论】:

    猜你喜欢
    • 2021-04-09
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-14
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多