winsock';s-recv函数

winsock';s-recv函数,c,client,winsock,recv,C,Client,Winsock,Recv,我有一个关于winsock的recv函数的一般性问题。 我用客户机/服务器架构编写了一个程序,其中客户机向服务器发送一个摄像头图像,服务器向客户机发送另一个图像。 客户端发送多个图像,直到程序关闭。服务器将用另一个映像响应每个接收到的映像 客户端(发送)--->服务器(接收)--->服务器(发送)--->客户端(接收)。 ^循环 我的问题是服务器接收功能。如果我使用512字节的大缓冲区多次调用receive函数,我如何知道我收到了整个图像? 我找到的示例只是等待连接关闭(recv返回0),但我希

我有一个关于winsock的recv函数的一般性问题。 我用客户机/服务器架构编写了一个程序,其中客户机向服务器发送一个摄像头图像,服务器向客户机发送另一个图像。 客户端发送多个图像,直到程序关闭。服务器将用另一个映像响应每个接收到的映像

客户端(发送)--->服务器(接收)--->服务器(发送)--->客户端(接收)。 ^循环

我的问题是服务器接收功能。如果我使用512字节的大缓冲区多次调用receive函数,我如何知道我收到了整个图像? 我找到的示例只是等待连接关闭(recv返回0),但我希望在不关闭连接的情况下接收多个图像。但是,如果在缓冲区中没有剩余字节之前接收,recv函数将停止线程,直到有新字节为止(但这永远不会发生,因为服务器在接收下一个字节之前首先要将自己的映像发送回客户端)


那么,是否有可能告诉服务器已接收到整个图像,以便它可以将自己的图像发送回客户端,而无需等待下一个字节或关闭的连接?

开发一个带有头的协议,其中包括接收方必须预期的数据量的大小
n
。接收器仅从TCP流读取头加
n
字节(由头指示)。然后你可以期待下一个标题。如果没有收到这些
n
字节,则传输不完整

简而言之,您可以在协议中定义消息,如下所示:

信息:

  • 数据长度(32位,无符号整数)
  • 数据内容

开发一个带有标头的协议,其中包括接收器必须预期的数据量的大小
n
。接收器仅从TCP流读取头加
n
字节(由头指示)。然后你可以期待下一个标题。如果没有收到这些
n
字节,则传输不完整

简而言之,您可以在协议中定义消息,如下所示:

信息:

  • 数据长度(32位,无符号整数)
  • 数据内容

将图像数据包装在包含以下内容的数据包中

  • 一个固定大小的标题,告诉后面有多少字节
  • 实际图像数据
在接收代码中,首先读取头部分,然后读取适当数量的数据

省略错误检查的示例代码;此外,您必须始终循环实际的recv调用,因为数据可能以碎片形式到达

unsigned bytesExpected;
Image imgData;
while( !LoopMustStop )
{
  Read( sizeof( unsigned ), bytesExpected );
  Read( bytesExpected, imgData );
  Process( bytesExpected, imgData )
}

将图像数据包装在包含以下内容的数据包中:

  • 一个固定大小的标题,告诉后面有多少字节
  • 实际图像数据
在接收代码中,首先读取头部分,然后读取适当数量的数据

省略错误检查的示例代码;此外,您必须始终循环实际的recv调用,因为数据可能以碎片形式到达

unsigned bytesExpected;
Image imgData;
while( !LoopMustStop )
{
  Read( sizeof( unsigned ), bytesExpected );
  Read( bytesExpected, imgData );
  Process( bytesExpected, imgData )
}

您也可以使用转义序列,但使用标头会更有效。包含大小和缓冲区的简单结构是否适合该问题,或者我是否需要几个send/recv调用来传输一个映像?我甚至会这样说:标头比迭代数据内容来处理/剥离转义更容易实现序列。确保所有通过网络传输的二进制数据都符合网络顺序(查看htonl、ntohl等)。如果您的软件将在多个平台上运行,这一点非常重要,但即使它只在Windows上运行,这也是一个好主意。@ben:看一下stijn的代码示例(下面是答案)-它为你的下一个研究提供了一个很好的基础。你也可以使用转义序列-但是使用头会更有效。一个简单的结构(包括大小和缓冲区)是否适合这个问题,或者我是否需要几个send/recv调用来传输一个图像?我甚至会这样说:头比迭代更容易实现检查数据内容以处理/剥离转义序列。确保所有通过线路的二进制数据都符合网络顺序(查看htonl、ntohl等)。如果您的软件将在多个平台上运行,这一点至关重要,但无论如何,这是一个好主意,即使它只在Windows上运行。@ben:看一看stijn的代码示例(下面的答案)-它为您的下一步研究提供了一个很好的基础。感谢您提供的快速示例,但实际上您应该记住字节顺序和头大小(
sizeof(unsigned)
可能会根据编译器的不同而变化)。协议设计可能会花费一些时间。感谢您提供的快速示例,但实际上您应该记住字节顺序和头大小(
sizeof(unsigned)
可能会根据编译器的不同而变化)。协议设计可能会花费一些时间。