//这是一个服务器端的recv程序,我想实现的功能就是当缓冲区没有数据的时候,按照设定的超时等待数据到来
//Conn为accept返回的SOCKET
//现在的问题就是select返回1,但是recv却没有收到数据
BYTE tmpBuf[20] = {0};
UINT ret = 0; TIMEVAL tv;
tv.tv_sec = 12;//超时设置为12S
tv.tv_usec = 0;
fd_set fdread;
FD_ZERO(&fdread);
FD_SET(Conn, &fdread);
ret = select(0, &fdread, NULL, NULL, &tv);//select第一个参数设置为Conn也没用
if (ret == SOCKET_ERROR)
{
cout<<"select recv socket error"<<endl;
return FALSE;
}
if ((ret > 0) && (FD_ISSET(Conn, &fdread)))
{
//这里执行到了,返回的ret却等于0
//第一次recv是可以的,第二次recv就出现这种现象了
//如果我加断点等待的话,通过监控软件,是可以看到数据到来的,在我上面设定的12S超时之内到来的,这时候再recv就可以了
//问题就是,为什么select返回1,但是数据却并没有到来,recv失败了
ret = recv(Conn,(char*)tmpBuf,4,0);
cout<<"recv = " << ret <<endl;
if(ret != 4)
{
cout<<"recv command length error!"<<endl; int er = WSAGetLastError(); cout<< "er = "<<er<<endl;
return FALSE;
}
else
{ UINT nLen = (tmpBuf[0] << 24) + (tmpBuf[1] << 16) +
(tmpBuf[2] << 8) + tmpBuf[3]; ret = recv(Conn,&recvBuf[4],nLen,0);
if(ret != nLen)
{
cout<<"recv command error!"<<endl; return FALSE;
}
else
{
return TRUE;
}
}
}
else
{
cout<<"select recv timeout!"<<endl;
return FALSE;
}
//Conn为accept返回的SOCKET
//现在的问题就是select返回1,但是recv却没有收到数据
BYTE tmpBuf[20] = {0};
UINT ret = 0; TIMEVAL tv;
tv.tv_sec = 12;//超时设置为12S
tv.tv_usec = 0;
fd_set fdread;
FD_ZERO(&fdread);
FD_SET(Conn, &fdread);
ret = select(0, &fdread, NULL, NULL, &tv);//select第一个参数设置为Conn也没用
if (ret == SOCKET_ERROR)
{
cout<<"select recv socket error"<<endl;
return FALSE;
}
if ((ret > 0) && (FD_ISSET(Conn, &fdread)))
{
//这里执行到了,返回的ret却等于0
//第一次recv是可以的,第二次recv就出现这种现象了
//如果我加断点等待的话,通过监控软件,是可以看到数据到来的,在我上面设定的12S超时之内到来的,这时候再recv就可以了
//问题就是,为什么select返回1,但是数据却并没有到来,recv失败了
ret = recv(Conn,(char*)tmpBuf,4,0);
cout<<"recv = " << ret <<endl;
if(ret != 4)
{
cout<<"recv command length error!"<<endl; int er = WSAGetLastError(); cout<< "er = "<<er<<endl;
return FALSE;
}
else
{ UINT nLen = (tmpBuf[0] << 24) + (tmpBuf[1] << 16) +
(tmpBuf[2] << 8) + tmpBuf[3]; ret = recv(Conn,&recvBuf[4],nLen,0);
if(ret != nLen)
{
cout<<"recv command error!"<<endl; return FALSE;
}
else
{
return TRUE;
}
}
}
else
{
cout<<"select recv timeout!"<<endl;
return FALSE;
}
{
WSADATA wsaData;
int status;
status = WSAStartup(MAKEWORD(2,2), &wsaData);
if (status != 0)
{
cout<<"WSAStartup error!"<<endl; return FALSE;
} if (LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2 )
{
cout<<"WSAData version error!"<<endl;
WSACleanup();
return FALSE;
} Socket = socket(AF_INET,SOCK_STREAM,/*IPPROTO_TCP*/0);
if(Socket == INVALID_SOCKET)
{
cout<<"socket error!"<<endl; return FALSE;
} int sendTimeout = 5000;
if(setsockopt (Socket,SOL_SOCKET,SO_SNDTIMEO,(char*)&sendTimeout,sizeof(int)) == SOCKET_ERROR)
{
cout<<"set send timeout error!"<<endl; return FALSE;
} int recvTimeout = 5000;
if(setsockopt (Socket,SOL_SOCKET,SO_SNDTIMEO,(char*)&recvTimeout,sizeof(int)) == SOCKET_ERROR)
{
cout<<"set recv timeout error!"<<endl; return FALSE;
} BOOL isOn = TRUE;
if(setsockopt (Socket,SOL_SOCKET,SO_REUSEADDR,(char*)&isOn,sizeof(isOn)) == SOCKET_ERROR)
{
cout<<"set SO_REUSEADDR error!"<<endl; return FALSE;
} if(setsockopt (Socket,IPPROTO_TCP,TCP_NODELAY,(char*)&isOn,sizeof(isOn)) == SOCKET_ERROR)
{
cout<<"set TCP_NODELAY error!"<<endl; return FALSE;
}
SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(_PORT); status = bind(Socket,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
if (status != 0)
{
cout<<"bind error!"<<endl; return FALSE;
} status = listen(Socket,5);
if (status != 0)
{
cout<<"listen error!"<<endl; return FALSE;
}
return TRUE;
}
{
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR); Conn = accept(Socket,(SOCKADDR*)&addrClient,&len);
if(Conn == INVALID_SOCKET)
{
cout<<"accept error!"<<endl;
}
else
{
char recvBuf[20] = {0};
int status; status = recv(Conn,recvBuf,20,0);
if(status < 1)
{
cout<<"recv error!"<<endl;
}
else
{
}
}
}
if(setsockopt (Socket,SOL_SOCKET,SO_SNDTIMEO,(char*)&recvTimeout,sizeof(int)) == SOCKET_ERROR)
{
cout < <"set recv timeout error!" < <endl; return FALSE;
}
感觉应该是
SO_RCVTIMEO
肯定是可以实现多次recv的,因为见过其它的软件实现过
我们现在就是想模仿那个软件
1楼是bind绑定端口代码
2楼是等待客户端连接到来代码运行顺序是1楼,2楼,客户端连接之后,和客户端进行收发操作,主楼就是其中收的操作