如何使用套接字recv(,,,)来获得不确定的响应长度

ryy*_*ker 1 c sockets windows

我需要使用IrDA套接字通信从设备发送命令和读取响应.尽管打包命令非常简单,但无法确定响应的预期大小.例如,命令"GET_ERRORS"导致设备将数据从0返回到n, \n每个分隔的行最多80个字节.我在这里阅读了帖子*,但实际数据块*之前的***标题并未由设备提供给我.

[编辑]
以下是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
%
Run Code Online (Sandbox Code Playgroud)

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

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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;
}
Run Code Online (Sandbox Code Playgroud)

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

Rem*_*eau 5

套接字消息必须以某种方式构成,以保证通信的完整性.例如,UDP数据报套接字发送/接收自包含消息,数据不能跨越消息边界.TCP流套接字没有该限制,因此必须使用描述消息长度的标头或消息数据中未出现的唯一终结符来分隔逻辑消息.IrDA插座也不例外.

由于您没有显示GET_ERRORS响应的实际数据或任何代码,但确实说响应消息的前面没有标题,那么只留下两种可能:

  1. 运输层面的消息框架.如果您使用该SOCK_DGRAM类型创建IrDA套接字,则会为您处理.如果您recv()使用的缓冲区太小,则会丢弃该消息,并且您会收到WSAEMSGSIZE错误消息.

  2. 在应用程序级别分隔消息.如果要使用SOCK_STREAM类型创建IrDA套接字,则必须自己处理.您提供任意缓冲区,并recv()使用可用的任何数据填充它,直到请求的大小.您只需recv()再次呼叫以接收更多数据,根据需要继续,直到找到您要查找的数据.

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