如何对不确定的响应长度使用套接字recv(,,,)
我需要使用IrDA套接字通信从设备发送命令和读取响应。尽管打包命令相当简单,但不可能确定响应的预期大小。例如,“GET_ERRORS”命令会导致设备返回0到n的数据,如何对不确定的响应长度使用套接字recv(,,,),c,windows,sockets,C,Windows,Sockets,我需要使用IrDA套接字通信从设备发送命令和读取响应。尽管打包命令相当简单,但不可能确定响应的预期大小。例如,“GET_ERRORS”命令会导致设备返回0到n的数据,\n分隔行,每行最多80字节。我已经阅读了post*,但是设备没有向我提供实际数据块前面的***标题* [编辑] 下面是GET_ERRORS命令的典型响应(为便于阅读而缩写): 如果我知道返回的数据长度,那么这个示例(来自SO post)可以很好地工作: int recv_all(int sockfd, void *buf, siz
\n
分隔行,每行最多80字节。我已经阅读了post*,但是设备没有向我提供实际数据块前面的***标题*
[编辑]下面是GET_ERRORS命令的典型响应(为便于阅读而缩写): 如果我知道返回的数据长度,那么这个示例(来自SO post)可以很好地工作:
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 recv\u all(int sockfd、void*buf、size\u t len、int标志)
{
尺寸=长度;
char*bufptr=(char*)buf;
而(探路者>0)
{
ssize_t rsz=recv(sockfd、bufptr、toread、flags);
如果(rsz只使用realloc将是我天真的建议。
这是我这里的一些旧代码的内部循环,收集灰尘
///////////// step 3 - get received bytes ////////////////
// Receive until the peer closes the connection
hdr->contentLen = 0;
while(1)
{
memset(hdr->readBuffer, 0, bufSize);
hdr->thisReadSize = recv (hdr->conn, hdr->readBuffer, bufSize, 0);
if ( hdr->thisReadSize <= 0 )
break;
// nasty - but seemingly necessary. Headers don't always include the content-length
// without a known content length, we cannot accurately allocate the memory required to hold
// the full (header+message) response. Therefore, we re-allocate our memory each time a successful read is performed.
// the alternative would be to write directly to file, or allocate (hopefully) more memory than we
// need (Too bad if we allocate 10 Mb & a resource is 10.1 Mb !)
hdr->result = (char*)realloc(hdr->result, hdr->thisReadSize+hdr->contentLen);
memcpy(hdr->result+hdr->contentLen, hdr->readBuffer, hdr->thisReadSize);
hdr->contentLen += hdr->thisReadSize;
}
//步骤3-获取接收的字节////////////////
//接收,直到对等方关闭连接
hdr->contentLen=0;
而(1)
{
memset(hdr->readBuffer,0,bufSize);
hdr->thisReadSize=recv(hdr->conn,hdr->readBuffer,bufSize,0);
如果(hdr->thisReadSize只使用realloc将是我天真的建议。
这是我这里的一些旧代码的内部循环,收集灰尘
///////////// step 3 - get received bytes ////////////////
// Receive until the peer closes the connection
hdr->contentLen = 0;
while(1)
{
memset(hdr->readBuffer, 0, bufSize);
hdr->thisReadSize = recv (hdr->conn, hdr->readBuffer, bufSize, 0);
if ( hdr->thisReadSize <= 0 )
break;
// nasty - but seemingly necessary. Headers don't always include the content-length
// without a known content length, we cannot accurately allocate the memory required to hold
// the full (header+message) response. Therefore, we re-allocate our memory each time a successful read is performed.
// the alternative would be to write directly to file, or allocate (hopefully) more memory than we
// need (Too bad if we allocate 10 Mb & a resource is 10.1 Mb !)
hdr->result = (char*)realloc(hdr->result, hdr->thisReadSize+hdr->contentLen);
memcpy(hdr->result+hdr->contentLen, hdr->readBuffer, hdr->thisReadSize);
hdr->contentLen += hdr->thisReadSize;
}
//步骤3-获取接收的字节////////////////
//接收,直到对等方关闭连接
hdr->contentLen=0;
而(1)
{
memset(hdr->readBuffer,0,bufSize);
hdr->thisReadSize=recv(hdr->conn,hdr->readBuffer,bufSize,0);
如果(hdr->thisReadSize套接字消息必须以某种方式构建,以保证通信的完整性。例如,UDP数据报套接字发送/接收自包含消息,数据不能跨越消息边界。TCP流套接字没有该限制,因此必须对逻辑消息进行分隔,例如它具有描述消息长度的标头,或消息数据中不显示的唯一终止符。IrDA套接字也不例外
由于您没有显示GET_ERRORS
响应的实际数据,也没有显示与此相关的任何代码,但确实表示响应消息前面没有标题,因此只剩下两种可能性:
传输级别的消息帧。如果您使用SOCK_DGRAM
类型创建IrDA套接字,则会处理此问题。如果您使用过小的缓冲区recv()
,则会丢弃消息,并会出现wsaemsgsgSize
错误
应用程序级别的消息定界。如果您使用SOCK\u流
类型创建IrDA套接字,您必须自己处理此问题。您提供任意缓冲区,并且recv()
使用任何可用数据填充它,直到请求的大小。您只需调用recv()
再次接收更多数据,根据需要继续,直到找到要查找的数据
我假设是后者,因为IrDA通常与套接字一起使用。我找不到任何基于IrDA的GET_ERRORS
命令的在线文档(您有这样的文档吗?),但我必须假设数据有一个您没有考虑的终止分隔符。它可能会向您发送0-n行,但我敢打赌最后一行的长度为0或等效值。在这种情况下,您只需调用recv()
在循环中,直到您收到终止符。套接字消息必须以某种方式设置帧,以保证通信的完整性。例如,UDP数据报套接字发送/接收自包含消息,数据不能跨越消息边界。TCP流套接字没有该限制,因此逻辑必须使用描述消息长度的标头或消息数据中未出现的唯一终止符来分隔消息。IrDA套接字也不例外
由于您没有显示GET_ERRORS
响应的实际数据,也没有显示与此相关的任何代码,但确实表示响应消息前面没有标题,因此只剩下两种可能性:
传输级别的消息帧。如果您使用SOCK_DGRAM
类型创建IrDA套接字,则会处理此问题。如果您使用过小的缓冲区recv()
,则会丢弃消息,并会出现wsaemsgsgSize
错误
应用程序级别的消息定界。如果您使用SOCK\u流
类型创建IrDA套接字,您必须自己处理此问题。您提供任意缓冲区,并且recv()
使用任何可用数据填充它,直到请求的大小。您只需调用recv()
再次接收更多数据,根据需要继续,直到找到要查找的数据
我假设是后者,因为IrDA通常与套接字一起使用。我找不到任何基于IrDA的GET_ERRORS
命令的在线文档(您有这样的文档吗?),但我必须假设数据有一个您没有考虑的终止分隔符。它可能会向您发送0-n行,但我打赌最后一行的长度为0,或等效值。在这种情况下,您只需在循环中调用recv()
,直到收到该终止符。您可以尝试类似的方法
将命令发送到设备。然后在循环内调用套接字上的epoll()或select(),以测试套接字是否已准备好接收数据。如果select()返回
///////////// step 3 - get received bytes ////////////////
// Receive until the peer closes the connection
hdr->contentLen = 0;
while(1)
{
memset(hdr->readBuffer, 0, bufSize);
hdr->thisReadSize = recv (hdr->conn, hdr->readBuffer, bufSize, 0);
if ( hdr->thisReadSize <= 0 )
break;
// nasty - but seemingly necessary. Headers don't always include the content-length
// without a known content length, we cannot accurately allocate the memory required to hold
// the full (header+message) response. Therefore, we re-allocate our memory each time a successful read is performed.
// the alternative would be to write directly to file, or allocate (hopefully) more memory than we
// need (Too bad if we allocate 10 Mb & a resource is 10.1 Mb !)
hdr->result = (char*)realloc(hdr->result, hdr->thisReadSize+hdr->contentLen);
memcpy(hdr->result+hdr->contentLen, hdr->readBuffer, hdr->thisReadSize);
hdr->contentLen += hdr->thisReadSize;
}