我创建了一个示例 TCP 连接函数。这使用带有超时的非阻塞套接字。该代码在我们的实验室中运行良好,但在某些网络中 TCP 连接失败并出现错误 115,这意味着 EINPROGRESS。调试后发现getsockopt()
将 iValopt 设置为 113,我们检查optvalue
是否等于 0,如果不是则返回失败。
操作系统:Linux Suse10
我的问题是:
- 这里粘贴的代码对吗?
- 为什么
getsockopt()
Opt 值设置为 113 而 errno 设置为 115?
我也注意到下面。
- 客户端有多个IP:174.66.45.22、58.68.445.112
- 服务器有多个IP:174.88.69.33、58.46.22.33
- 如果我将绑定地址设置为 174.66.45.22 并连接到 174.88.69.33 总是成功的。
- 如果我将绑定地址设置为 174.66.45.22 并连接到 58.46.22.33 将失败。
- 但是,如果我只是在第一次运行时将绑定地址设置为 58.68.445.112,在第二次运行时我将绑定地址更改为 174.66.45.22,然后连接到 58.46.22.33 是成功的!
你能解释一下为什么吗?
我在这里粘贴的确切代码
int tcp_sockconnect_linux(int iSocket, const struct sockaddr* pstSockAddr, unsigned int uiSockAddrLen, unsigned int uiConnectionTimeout)
{
int iRet = 0;
//int iValopt = 0;
int iLength = 0;
struct timeval stTv;
fd_set write_fds;
(void)fcntl((int)(long)iSocket, F_SETFL, O_NONBLOCK);
iRet = connect((int)(long)iSocket, (struct sockaddr*) pstSockAddr, uiSockAddrLen);
if (iRet < 0)
{
if (errno == EINPROGRESS)
{
stTv.tv_sec = uiConnectionTimeout;
stTv.tv_usec = 0;
FD_ZERO(&write_fds);
FD_SET((int)(long)iSocket, &write_fds);
if (0 < select(((int)(long)(iSocket)) + 1,NULL, &write_fds, NULL, &stTv))
{
iLength = sizeof(int);
if (0 > getsockopt((int)(long)iSocket, SOL_SOCKET,SO_ERROR, (void*)(&iValopt), &iLength))
{
return -1;
}
if (0 != iValopt)
{
return -1;
}
return 2;
}
else
{
return -1;
}
}
else
{
return -1;
}
}
return 2;
}
int create_socket(void)
{
int iRet, sock_sd;
struct sockaddr_in saServer;
struct sockaddr_in saLocal;
#ifdef WIN32
WSADATA wsaData;
if(WSAStartup(0x101, &wsaData))
{
printf("Unable to initialize WinSock library.\n");
}
#endif
memset (&saLocal,'\0', sizeof(saLocal));
saLocal.sin_family = AF_INET;
saLocal.sin_addr.s_addr = inet_addr(strBindAddr);
saLocal.sin_port = htons(0);
sock_sd = socket(AF_INET,SOCK_STREAM,0);
memset (&saServer,'\0', sizeof(saServer));
saServer.sin_family = AF_INET;
saServer.sin_addr.s_addr = inet_addr (strServerIP);
saServer.sin_port = htons(uiServerPort);
iRet = bind((unsigned int)sock_sd,(struct sockaddr*) &saLocal,sizeof(saLocal));
#ifdef WIN32
if (iRet == SOCKET_ERROR)
{
printf("\nTCP Bind Failed to LocalIP %s\n",strBindAddr);
}
#else
if (-1 == iRet)
{
printf("\nTCP Bind Failed to LocalIP %s\n",strBindAddr);
}
#endif
#ifdef WIN32
iRet = tcp_sockconnect_win(sock_sd, (struct sockaddr*) &saServer,sizeof(saServer),uiConnectionTimeOut);
if (iRet == SOCKET_ERROR)
{
printf("\nTCP Socket Connect Failed with ErrorNo = %d iValopt = %d LineNo = %d \n",WSAGetLastError(),iValopt,iLineNo);
}
else if (2 == iRet)
{
printf("\nTCP Socket Connect Success \n");
}
#else
iRet = tcp_sockconnect_linux(sock_sd, (struct sockaddr*) &saServer,sizeof(saServer),uiConnectionTimeOut);
if(-1 == iRet)
{
printf("\nTCP Socket Connect Failed with ErrorNo = %d iValopt = %d LineNo = %d\n",errno,iValopt,iLineNo);
}
else if (2 == iRet)
{
printf("\nTCP Socket Connect Success %d\n",iLineNo);
}
#endif
#ifdef WIN32
closesocket (sock_sd);
#else
close(sock_sd);
#endif
return 0;
}
int main ()
{
int iRet = 0;
printf ("Enter the Bind Address (Local IP): ");
scanf("%s" ,&strBindAddr);
printf ("\nEnter the IP Address of Server : ");
scanf("%s" ,&strServerIP);
printf ("\nEnter the PORT Number of Server : ");
scanf("%d" ,&uiServerPort);
printf ("\nEnter the Connection timeout in Seconds : ");
scanf("%d", &uiConnectionTimeOut);
iRet = create_socket();
return 0;
}