我需要使用 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 ,那么只剩下两种可能性:
传输级别的消息框架。如果您使用
SOCK_DGRAM
类型创建 IrDA 套接字,则会为您处理此问题。如果您recv()
使用的缓冲区太小,消息将被丢弃,您会收到WSAEMSGSIZE
错误。在应用层定界消息。如果您使用
SOCK_STREAM
类型创建 IrDA 套接字,则必须自己处理。您提供一个任意缓冲区,recv()
将可用的任何数据填充到其中,直至达到请求的大小。您只需再次调用recv()
即可接收更多数据,并根据需要继续调用,直到找到您要查找的数据。
我假设是后者,因为这是 IrDA 通常与套接字一起使用的方式。我找不到任何基于 IrDA 的 GET_ERRORS
命令的在线文档(你有这样的文档吗?),但我必须假设数据有一个你没有考虑的终止分隔符。它可能会向您发送 0-n 行,但我敢打赌最后一行的长度为 0,或等价物。在这种情况下,您只需在循环中调用 recv()
,直到收到该终止符。
关于c - 如何将套接字 recv(,,,) 用于不确定的响应长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18989663/