1

アクティブな接続を 1 つだけ受け入れる標準 (socket.h) ライブラリを使用して、サーバー C++ サーバー プログラム (Linux で) を実装したいと考えています。これを実装する方法についての私の理解は次のとおりです(エラーチェックを削除しました):

int port = 4711;
int MAXCONNECTIONS = 5;

int m_sock;
m_sock = socket ( AF_INET, SOCK_STREAM,  0 );

int on = 1;
setsockopt ( m_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof ( on ) ) < 0

sockaddr_in m_addr;
m_addr.sin_family = AF_INET;
m_addr.sin_addr.s_addr = INADDR_ANY;
m_addr.sin_port = htons ( port );

bind ( m_sock, ( struct sockaddr * ) &m_addr,
                           sizeof ( m_addr ) );

listen ( m_sock, MAXCONNECTIONS );

// now accept new connection and get socket
int con_sock;
int addr_length = sizeof ( m_addr );
con_sock = accept ( m_sock, ( sockaddr * ) &m_addr, ( socklen_t * ) &addr_length );

これは私のコードでこれまでのところ機能します。ただし、作成された最初のソケットは引き続き接続を受け入れます。私が理解している限り、最初のソケットを閉じる必要があります。

close ( m_sock );

これにより、新しい接続が妨げられます。しかし、最初の接続が切断されたときに、接続を再確立することができません。私の理解では、上記と同じ手順を繰り返さなければなりません。

私が遭遇したのは、ブロックして接続を待機するところを受け入れるまでコードが正常に実行されますが、接続しているクライアントは「接続が拒否されました」を受け取り、netstat に LISTEN ポートが表示されないことです。

あなたはなにか考えはありますか?

他の接続を受け入れてすぐに閉じるオプションは、ここでは考慮されません。

4

3 に答える 3

1

accept(2)必要になるまで、新しい接続を行わないでください。受け入れ、クライアントダイアログの処理、および接続されたソケットのクローズをループします。

于 2012-12-10T18:36:31.313 に答える
0

まず、リスニングソケットと接続されたソケットを区別しましょう。リスニングソケットは、サーバーがリッスンする、つまりクライアントを待機するソケットです。acceptの呼び出しが戻ると、クライアントとの3ウェイハンドシェイクが完了し、acceptが接続されたソケットを返すことを意味します。接続されたソケットは、クライアントとの実際の通信が行われるソケットです。

あなたの例でm_sockは、はリスニングソケットでcon_sockあり、は接続されたソケットです。'm_sock'を閉じると、実際にはリスニングソケットが閉じられるため、サーバーはこれ以上接続を受け入れることができなくなります。そのため、クライアント側で接続がエラーを拒否しました。

一度に1つのリクエストのみを処理することがタスクである場合、必要なのは反復サーバーだと思います。次のリクエストは前のリクエストが完全に処理された後にのみ処理されるため、リスニングソケットを閉じる必要はありません。

listen ( m_sock, MAXCONNECTIONS );

// now accept new connection and get socket
int con_sock;
int addr_length = sizeof ( m_addr );
for(;;)
{
        con_sock = accept ( m_sock, ( sockaddr * ) &m_addr, ( socklen_t * ) &addr_length );
        //do your task
        close(con_sock);
}

1つの要求の処理中に他の接続への接続を拒否する場合は、バックログ値を1に減らすことができます。ただし、これはECONNREFUSEクライアントにエラーを送信せず、クライアント要求を無視します。ただし、サーバーがアイドル状態の場合でも、サーバーがキューに保持する接続は1つだけです。(なぜ実際にこれを実行したいかはわかりません。)

于 2012-12-10T18:30:23.920 に答える
0

まず、コードの 2 行目を変更してみてください (現在はint MAXCONNECTIONS = 5;)

于 2012-12-10T18:15:26.300 に答える