您好!
我的客户正在尝试使用具有 NDK 协议栈的 UDP 协议通过以太网电缆捕获摄像头数据。
他们遇到的问题是、如果传入的数据被碎片化到多个数据包、他们的应用程序将丢失最终的数据包。 请注意、他们使用 ProcSDK 版本03.01.00进行开发。
他们的应用程序使用 BSD 套接字 API 进行数据捕获,其代码如下所示:
#define APP_IP_ADDRESS"192.168.1.2"
静态常量 uint16_t GVSP_APP0_UDP_PORTNUM= 60001;
静态常量 uint16_t STREPORT_PACKETSIZE= 1400;
静态常量 uint32_t IP_HEADER_SIZE= 20;// IP 头大小 uint16_t
头大小= uint8_tudp_t_t_size;
静态 INT8_uDP_t_t_size =静态头文件大小= 8;静态 INT8_tu_v3_uDP_t_size = u_v3_t_size = uDP_int8头// GVSP 报头大小
静态 const uint32_t GVSP_PACKETSIZE= STREE_PACKETSIZE - IP_HEADER_SIZE - UDP_HEADER_SIZE;// UDP 数据包大小。 接收缓冲区大小
静态空 CaptureStream (const socket StreamSock){
char buff[GVSP_PACKETSIZE]={0};
while (TRUE){
int bytes = recv (streamSock、buff、sizeof (buff)、0);
// int bytes = recv (sizamsock、MSG、eof (buff
)、如果无效、则为0)、则为0)
}
静态 bool InitStreamChannel (socket &StreamSock,struct sockaddr_in &StreamAppAddr){fdOpenSession(
TaskSelf());
//***** 创建套接字 //
StreamSock = socket (AF_iNet、SOCK_DGRAM、0);
if (StreamSock = INVALID_SEocket){
ReleaseSocket (StreamSock);
CDebugLog (DBM_camera2、"无法创建 UDP 套接字\r\n");
return false;
}
memset (&StreamAppAddr、Addr)
StreamAppAddr.Sin_Family = AF_iNet;
StreamAppAddr.Sin_port = htons (GVSP_APP0_UDP_PORTNUM);
inet_pton (AF_iNet、APP_IP_ADDRESS、&(StreamAppAddr.Sin_addr));
if (bind (StreamSock、(struct sockdr *)&StreamAppAddr、sizeof (StreamAppAddr))== socket_error){
ReleaseSocket (StreamSock);
CsockLog (DBM_camera2、"无法绑定 UDP 套接字\r\n");
return false;
}
= socksockpit (stroct、socknum、enchar) sizeof (recnum)= socket_error){
返回 false;
}
#if 1
struct timeval 超时;
timeout.tv_sec = 0;
timeout.tv_usec = 100 * 1000;
if (setsockopt (StreamSock、SOL_socket、SO_RCVTIMEO、(char *)&timeout、 sizeof (timeout)!= 0){
return false;
}
#endif
return true;
}
class StreamChannelTask:public nTask{
public:
virtual void TaskFunc (uint32_t arg){
socket StreamStreamStrek;
struct socksaddr_in SocketAppAddr;
while (!InitStreamChannel (uintx32_t r)
r) sockeStream (capture/r)、sockn)、socksockeRit
(unit (sockn)、sockeStream (unit)、sockn)、sockeRit (unit、sockn)
//生成捕获结束事件
CSetEvent(camera.EndCaptureEvent);
}
}}}}}}}}}{streamchanneltask;
这里是它们的调试状态。
-输入数据缓冲区在其应用程序中为1372字节。 这是传入数据流的最大数据包有效载荷。 这已通过 Wireshark 验证。
他们只是尝试增加这个接收缓冲器,但它没有帮助。
-如果从摄像机发送非碎片数据,即,如果可以 将传入的数据容纳在单个 UDP 有效载荷中,则捕获的数据似乎总是正确的。
由于摄像头应用程序的原因,传入的数据始终是大量的数据,因此传入的数据基本上被碎片化成如此多的数据包。 在这种情况下,最后一个数据包的 recv()函数总是被卡住。 我的意思是、控制不会返回到应用程序(在 recv 函数中阻止)、最终应用程序会丢失最终数据。
-如果他们将此应用程序代码转换为 Windows 应用程序(使用 winsocket),他们总是能够成功地从相机捕获所有数据。
-堆栈线程在其应用程序中具有最高的优先级。 任何其他用户线程都使用较低的优先级。
即使在通信中引入了数据包间延迟,他们仍然会看到问题。 最后一个数据包始终丢失。
-更改为具有多个 PBM 缓冲器不起作用。
-使用 SO_RCVLOWAT 和 SO_RCVTIME 等套接字级别选项 不起作用。
-使用诸如 MSG_DONTWAIT 之类的 recv API 版本选项不起作用。
您对此问题是否有任何疑问? 请提供任何帮助。
由于从摄像头捕获数据对于其应用非常重要、因此我们需要尽快提供解决此问题的建议。
此致、
Naoki