外部控制器每30ms通过TCP/IP套接字发送120个字节的消息。 应用程序通过标准的tcp/ip套接字recv函数接收此消息。 它在Linux下完美工作& OSX(recv每30ms返回120字节的消息)。 在Windows下recv大约每1秒返回〜3500字节的缓冲区。其余时间返回0. Windows下的Wireshark显示消息确实每隔30ms进入一次。Windows TCP套接字接收延迟
如何使Windows的TCP套接字正常工作(没有延迟)?
PS:我已经玩过TCP_NODELAY & TcpAckFrequency了。 Wireshark显示一切正常。所以我认为这是一些Windows优化,应该关闭。
Reading--
int WMaster::DataRead(void)
{
if (!open_ok) return 0;
if (!CheckSocket())
{
PrintErrNo();
return 0;
}
iResult = recv(ConnectSocket, (char *)input_buff,sizeof(input_buff),0);
nError=WSAGetLastError();
if(nError==0) return iResult;
if(nError==WSAEWOULDBLOCK) return iResult;
PrintErrNo();
return 0;
}
Initialization-
ConnectSocket = INVALID_SOCKET;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&clientService, sizeof(clientService));
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr(deviceName.toLatin1().constData());
clientService.sin_port = htons(port);
iResult = setsockopt(ConnectSocket, IPPROTO_TCP, TCP_NODELAY, (char *) &flag,
sizeof (int));
u_long iMode=1;
iResult=ioctlsocket(ConnectSocket,FIONBIO,&iMode);
iResult = ::connect(ConnectSocket, (SOCKADDR*) &clientService,
sizeof(clientService));
CheckSocket -
bool WMaster::CheckSocket(void)
{
socklen_t len = sizeof (int);
int retval = getsockopt (ConnectSocket, SOL_SOCKET, SO_ERROR, (char*)(&valopt), &len);
if (retval!=0)
{
open_ok=false;
return false;
};
return true;
}
这很奇怪。你是否在这个套接字上设置了其他套接字选项?想到SO_RCVLOWAT,但在Windows上记录为不支持。另外,你说recv()在剩下的时间里“返回0”。如果套接字被远程端关闭,recv()将只返回0 - 即使套接字被设置为非阻塞。你能发布显示你如何创建和初始化套接字的代码吗? – selbie 2013-03-23 17:10:34
我添加套接字初始化(iResult解析被剥离) – question2013 2013-03-24 21:22:07
你可以分享你的代码,“调用recv”循环“?你的套接字是非阻塞的,并且你没有显示调用select或等待数据到达的代码。此外,如果recv()返回SOCKET_ERROR,则应该只调用WSAGetLastError。无法保证recv会在成功调用时将错误状态重新设置为0。 – selbie 2013-03-25 03:52:41