0

現在、setsockopt()次のコードを使用してオプションを指定しようとしています。

// bind socket
// Use setsockopt() function to make sure the port is not in use
int yes = 1;
setsockopt(TCPSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
setsockopt(TCPSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
status = bind(TCPSocket, host_info_list->ai_addr, host_info_list->ai_addrlen);
if (status == -1)  std::cout << "bind error" << std::endl ;

// listen for connections
status =  listen(TCPSocket, 5);
if (status == -1)  std::cout << "listen error" << std::endl ;

int new_sd;
struct sockaddr_storage their_addr;
socklen_t addr_size = sizeof(their_addr);
new_sd = accept(TCPSocket, (struct sockaddr *)&their_addr, &addr_size);
if (new_sd == -1) std::cout << "listen error" << std::endl ;

Notetvは既に指定された timeval です。

最初のsetsockopt()呼び出しだけを行うと、すべて正常に動作します。ただし、2 番目 (エラーを返さない) を追加すると、コードで指定された 2 番目の「リッスン エラー」が発生します。タイムアウト値の設定がこれに影響する理由がわかりません。誰か説明できますか?

指定されたコードの功績は認めません。ここのチュートリアルに示されているコードから変更されています: http://codebase.eu/tutorial/linux-socket-programming-c/

4

2 に答える 2

2

このようなTCP 状態図を見るとTIME_WAIT、アクティブにソケットを閉じるときに呼び出される状態があることがわかります。この状態が終了するまでには、 RFC793によると最大 4 分かかる場合があります。

ソケットがTIME_WAIT待機状態にある間は、待機状態にあるソケットと同じアドレスとポートのペアを使用してインターフェイスにバインドすることはできません。ソケットにフラグを設定SO_REUSEADDRすると、現在のソケット (フラグが設定されている) がそのTIME_WAIT状態にあるときに、他のソケットがそのアドレスにバインドできるようになります。

このSO_REUSEADDRオプションは、サーバー (パッシブ、リッスン) ソケットに最も役立ちます。


あなたの問題に関しては、各呼び出しの後、setsockoptそれが返すものを確認し、そうである場合は、何が問題なのか-1を確認errnoします。perrorまたはを使用strerrorして、エラーの印刷可能な文字列を印刷または取得できます。

if (setsockopt(TCPSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0)
{
    std::cerr << "Error setting the SO_REUSEADDR: " << strerror(errno) << '\n';
    // Do something appropriate
}
于 2015-11-23T06:57:03.457 に答える
0

Joachim のソリューションは、私の最初の質問に答え、setsockopt() を説明するという素晴らしい仕事をしました。問題がコードのさらに下にあることに気付いた後、私自身の質問に答えるために、タイムアウトはサーバーがポートをリッスンできることに影響します。タイムアウトがわずか 10 ミリ秒であるとすると、サーバーを起動してからクライアントを起動し、その間に接続を確立する必要があります。私の場合、これは発生していなかったため、エラーが発生しました。

于 2015-11-23T07:20:39.123 に答える