サンプルの TCP 接続関数を作成しました。これは、タイムアウト付きのノンブロッキング ソケットを使用します。私たちのラボではコードは正常に動作していますが、一部のネットワークでは TCP 接続がエラー 115 で失敗し、これは EINPROGRESS を意味します。デバッグが見つかった後getsockopt()
、iValopt を 113 に設定し、optvalue
ゼロに等しいことを確認します。そうでない場合は失敗を返します。
OS: 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
- Bind アドレスを 174.66.45.22 に設定して 174.88.69.33 に接続すると、常に成功します。
- Bind アドレスを 174.66.45.22 に設定して 58.46.22.33 に接続すると失敗します。
- しかし、最初の実行でバインド アドレスを 58.68.445.112 に設定し、2 回目の実行でバインド アドレスを 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;
}