クライアント側のSO_REUSEADDRについて
簡単なTCPクライアントを自ポート固定で作成しようと思っています。ですが、クライアントからコネクションをクローズすると、次に接続する際に数分待たなければ通信しません。TIME_WAITが関係していることまではわかったので、以下のサイトを参考にSO_REUSEADDRオプションを設定することにしました。ですが、それでも問題は解決されませんでした。一体何が悪いのでしょうか。
以下にサンプルコードを示します。一回目のループではコネクションが成功し、アクティブクローズした後の二回目はconnect()で失敗します。
#include <stdio.h>
#include <winsock2.h>
int communicate(char *deststr, int dstport, int srcport) {
struct sockaddr_in client;
struct sockaddr_in server;
SOCKET sock;
int ret;
BOOL yes = 1;
char inbuf[2048];
sock = socket(AF_INET, SOCK_STREAM, 0);
// SO_REUSEADDR を ON にする
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&yes, sizeof(yes));
// サーバー側のアドレスとポートを指定する
server.sin_family = AF_INET;
server.sin_port = htons(dstport);
server.sin_addr.S_un.S_addr = inet_addr(deststr);
// クライアント側のポートを固定にする
client.sin_family = AF_INET;
client.sin_port = htons(srcport);
client.sin_addr.S_un.S_addr = INADDR_ANY;
// ソケットをバインドする。ここではエラーは起こらない。
ret = bind(sock, (struct sockaddr *)&client, sizeof(client));
if (ret) {
closesocket(sock);
printf("bind error : %X\n", ret);
return ret;
}
// ここでエラーが発生。エラーコードはFFFFFFFF
ret = connect(sock, (struct sockaddr *)&server, sizeof(server));
if (ret) {
closesocket(sock);
printf("connect error : %X\n", ret);
return ret;
} else {
closesocket(sock);
printf("returned communicate()\n");
return ret;
}
}
// 指定のアドレス、ポートに接続し、接続できたらすぐさま切断し、次のコネクションを張る
int main(int argc, char *argv[]) {
WSADATA wsaData;
WSAStartup(MAKEWORD(2,0), &wsaData);
while(1) {
int ret = communicate("192.168.0.10", 12345, 23456);
if(ret) {
break;
}
};
WSACleanup();
return 0;
}