bool EnableBlockSocket(bool bEnable)
{
INT nResult = -1;
INT nOption = fcntl(m_nFD, F_GETFL, 0);
if (nOption >= 0)
{
if (bEnable)
{
nOption &= ~O_NONBLOCK;
}
else
{
nOption |= O_NONBLOCK;
}
nResult = fcntl(m_nFD, F_SETFL, nOption);
}
assert(nResult >= 0);
return (nResult >= 0);
}
bool Connect(INT nTimeout/* = 30*/)
{
bool bResult = FALSE;
if (INVALID_SOCKET == m_nFD)
{
m_nFD = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == m_nFD)
{
LOG_ERROR("Fail to create socket:%s\n", strerror(errno));
return bResult;
}
}
//设置为非阻塞模式
EnableBlockSocket(FALSE);
struct sockaddr_in sa;
bzero(&sa, sizeof(struct sockaddr_in));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = HTONL(m_nIP);
sa.sin_port = HTONS(m_nPort);
//建立连接
bResult = (connect(m_nFD, (struct sockaddr*)&sa, sizeof(sa)) != SOCKET_ERROR);
if (!bResult)
{
// 非阻塞模式返回未完成
if (errno == EINPROGRESS)
{
LOG_DEBUG("unblock mode socket is connecting...\n");
fd_set objFDSet;
FD_ZERO(&objFDSet);
FD_SET(m_nFD, &objFDSet);
timeval tm;
tm.tv_sec = nTimeout;
tm.tv_usec = 0;
//select后需要坚持错误码
if (select(m_nFD + 1, NULL, &objFDSet, NULL, &tm) > 0
&& FD_ISSET(m_nFD, &objFDSet))
{
int nErr = 0;
socklen_t len = sizeof(nErr);
if (0 == getsockopt(m_nFD, SOL_SOCKET, SO_ERROR, &nErr, &len))
{
if (0 == nErr)
{
bResult = true;
}
else
{
LOG_ERROR("Fail to connnect host:%s\n", strerror(nErr));
}
}
}
}
else
{
LOG_ERROR("Fail to connnect host:%s\n", strerror(errno));
}
}
//恢复为阻塞模式
EnableBlockSocket(TRUE);
return bResult;
}