客户端首先将socket设置为非阻塞,建立连接
bool TcpRspObject::createSocketAndConnect()
{
if(m_listenfd > 0)
return true;
m_listenfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(m_listenfd < 0)
{
qDebug()<<"socket error";
return false;
}
//设置Socket为非阻塞模式
int iMode = 1;
int retVal = ioctlsocket(m_listenfd, FIONBIO, (u_long FAR*)&iMode);
if (retVal == SOCKET_ERROR)
{
printf("ioctlsocket failed!\n");
WSACleanup();
return -1;
}
//连接到服务器
int retVal0;
while (true)
{
retVal0 = ::connect(m_listenfd,(struct sockaddr*)&m_serverAddr,sizeof(m_serverAddr));
if (SOCKET_ERROR == retVal0)
{
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK || err == WSAEINVAL)
{
QThread::msleep(500);
continue;
}
else if (err == WSAEISCONN)
{
break;
}
else
{
printf("connection failed!\n");
closesocket(m_listenfd);
m_listenfd = -1;
WSACleanup();
QThread::msleep(500);
return false;
}
}
}
return true;
}
非阻塞接收情况 讨论:
void TcpRspObject::slotRecvData()
{
int nLength = 0;
createSocketAndConnect();
while(true)
{
// if(createSocketAndConnect())
//{
char pBuf[500*1024] = {0};
int readLen = 0;
readLen = recv(m_listenfd, (char*)pBuf, 500*1024,0);
nLength += readLen;
if (SOCKET_ERROR == readLen)
{
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK)
{
QThread::msleep(100);
printf("waiting back msg!\n");
continue;
}
else if (err == WSAETIMEDOUT || err == WSAENETDOWN)
{
printf("recv failed!\n");
closesocket(m_listenfd);
m_listenfd = -1;
WSACleanup();
QThread::msleep(100);
continue;
}
else if(err ==WSAENOTSOCK)
{
QThread::msleep(100);
printf("描述字为非套接字\n");
continue;
}
else{
QThread::msleep(100);
continue;
}
}
//调用环形缓冲的处理函数
m_pCustomBuff->Do(pBuf, readLen);
}
}
一般情况下,非阻塞接收使用较少,这里原因具体还不是很清楚,希望懂得人多多指教。
下边是阻塞接收,recv只有在socket断开(返回0)或者接收到数据才会返回,否则一直阻塞等待
void TcpRspObject::slotRecvData()
{
int nLength = 0;
while(true)
{
if(createSocketAndConnect())
{
char pBuf[500*1024] = {0};
int readLen = 0;
readLen = recv(m_listenfd, (char*)pBuf, 500*1024,0);
nLength += readLen;
//qDebug() << "recvLenth" << QString::number(nLength);
if(readLen<=0)
{
//这里需要重连,清空环形缓冲区
m_pCustomBuff->Clear();
#ifdef Q_OS_WIN
closesocket(m_listenfd);
#else
close(m_listenfd);
#endif
m_listenfd = -1;
QThread::sleep(10);
continue;
}
//调用环形缓冲的处理函数
m_pCustomBuff->Do(pBuf, readLen);
}
else
{
QThread::sleep(10);
continue;
}
}
closesocket(m_listenfd);
m_listenfd = -1;
QThread::sleep(10);
}