c - 如何将套接字 recv(,,,) 用于不确定的响应长度

标签 c windows sockets

我需要使用 IrDA 套接字通信从设备发送命令和读取响应。尽管打包命令相当简单,但无法确定响应的预期大小。例如,命令“GET_ERRORS”导致设备返回从 0 到 n 的数据,\n 分隔行,每行最多 80 个字节。我已阅读帖子 * here ,但设备未向我提供实际数据 block 之前的*** header *

[编辑]
这是 GET_ERRORS 命令的典型响应(为了便于阅读而简称):

Date       Time     Fault
10/12/2000 02:00:00 3f46
10/12/2000 02:00:00 bcf5
10/12/2000 02:00:00 1312
10/12/2000 02:00:00 a334
10/12/2000 02:00:00 b212
10/12/2000 02:00:00 b212
10/12/2000 02:00:00 c43a
%

这个例子(来自 SO post HERE )如果我知道返回数据的长度,效果很好:

int recv_all(int sockfd, void *buf, size_t len, int flags)
{
    size_t toread = len;
    char  *bufptr = (char*) buf;

    while (toread > 0)
    {
        ssize_t rsz = recv(sockfd, bufptr, toread, flags);
        if (rsz <= 0)
            return rsz;  /* Error or other end closed cnnection */

        toread -= rsz;  /* Read less next time */
        bufptr += rsz;  /* Next buffer position to read into */
    }

    return len;
}

但是如果我想接收未知数量的数据,我唯一知道要做的就是声明一个大缓冲区,然后将它传递给这样的东西:

int IrdaCommReceive(int irdaCommSocket, void* largeBuf, size_t len, int* rcvd)
{
    char *bufptr = (char *)largeBuf;

    int bytesRcvd = recv(irdaCommSocket, bufptr, len, 0);

    if (bytesRcvd < 0) return WSAGetLastError();
    *rcvd = bytesRcvd;

    return 0;
}

有没有更好的方法来为不确定大小的套接字数据编写接收函数?

最佳答案

套接字消息必须以某种方式构造以保证通信的完整性。例如,UDP 数据报套接字发送/接收自包含消息,数据不能跨越消息边界。 TCP 流套接字没有该限制,因此必须改为使用描述消息长度的 header 或未出现在消息数据中的唯一终止符来分隔逻辑消息。 IrDA socket 也不异常(exception)。

由于您没有显示 GET_ERRORS 响应的实际数据,或与此相关的任何代码,但确实说响应消息的前面没有 header ,那么只剩下两种可能性:

  1. 传输级别的消息框架。如果您使用 SOCK_DGRAM 类型创建 IrDA 套接字,则会为您处理此问题。如果您 recv() 使用的缓冲区太小,消息将被丢弃,您会收到 WSAEMSGSIZE 错误。

  2. 在应用层定界消息。如果您使用 SOCK_STREAM 类型创建 IrDA 套接字,则必须自己处理。您提供一个任意缓冲区,recv() 将可用的任何数据填充到其中,直至达到请求的大小。您只需再次调用 recv() 即可接收更多数据,并根据需要继续调用,直到找到您要查找的数据。

我假设是后者,因为这是 IrDA 通常与套接字一起使用的方式。我找不到任何基于 IrDA 的 GET_ERRORS 命令的在线文档(你有这样的文档吗?),但我必须假设数据有一个你没有考虑的终止分隔符。它可能会向您发送 0-n 行,但我敢打赌最后一行的长度为 0,或等价物。在这种情况下,您只需在循环中调用 recv(),直到收到该终止符。

关于c - 如何将套接字 recv(,,,) 用于不确定的响应长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18989663/

相关文章:

c - C 中自定义 getln 函数缺少原型(prototype)错误消息的解释

linux - Python远程编程/调试

android - Android客户端错误-java.lang.IllegalStateException : Could not execute method of the activity

java - 同时建立多个 TCP 连接

c - 用户模式和内核模式下的线程

c# - 如何获取 liblz4.dll

windows - 为什么 git-upload-pack(在 git clone 期间)会挂起?

android - 将 Android 开发人员从 Linux 过渡到 Windows : toolchain signes APK differently?

python - 为什么我的网络在传递数据之前要等到套接字或 websocket 连接关闭

c - 是否有任何浮点密集型代码在任何基于 x86 的架构中产生位精确的结果?