4

私は単純なTCPサーバーを書いています。私が考えたモデルは、サーバーがメインスレッドでクライアント接続を受け入れ、それらを別のスレッドに引き渡して、サーバーが再び接続をリッスンできるようにすることです。私が使用したコードの関連部分を以下に掲載します。

接続を受け入れる:

void startServer () {

    int serverSideSocket = 0;
    int clientSideSocket = 0;

    serverSideSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSideSocket < 0) {
        error("ERROR opening socket");
        exit(1);
    }

    clientAddressLength = sizeof(clientAddress);
    memset((char *) &serverAddress, 0, sizeof(serverAddress));
    memset((char *) &clientAddress, 0, clientAddressLength);

    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = INADDR_ANY;
    serverAddress.sin_port = htons(32000);

    if (bind(serverSideSocket, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {
        error("ERROR on binding");
        exit(1);
    }      

    listen(serverSideSocket, SOMAXCONN);

    while(true) {
        clientSideSocket = accept(serverSideSocket, (struct sockaddr *) &clientAddress, &clientAddressLength);

    if (clientSideSocket < 0)
            error("ERROR on accept");

        processingThreadGroup->create_thread(boost::bind(process, clientSideSocket, this));
    }

}

ここで、processingThreadGroup は boost::thread_group インスタンスです。プロセスメソッドでは:

void process (int clientSideSocket, DataCollector* collector) {

int numberOfCharactersRead = 0;
string buffer;

do {
      char msgBuffer[1000];
      numberOfCharactersRead = recv(clientSideSocket, msgBuffer, (1000 - 1), 0);
      if (numberOfCharactersRead < 0) {
          //display error
          close(clientSideSocket);
      }
      else if (numberOfCharactersRead == 0)
          close(clientSideSocket);
      else {
          printf("%s", msgBuffer);
          memset(msgBuffer, 0, 1000);
      }
   } while (numberOfCharactersRead > 0); 
}

しかし、コードをデバッグすると、処理スレッドが呼び出されると、メイン スレッドが接続を受け入れなくなっていることがわかりました。データは process() メソッド内でのみ読み取られます。メインスレッドはもう実行されていないようです。私が取ったアプローチの問題とそれを修正するための提案は何ですか?

編集:ここで問題を見つけたと思い、回答として更新しました。私は自分の質問に答えたので、それを受け入れません。みんな助けてくれてありがとう!

4

1 に答える 1

1

問題を見つけたと思います。これをサーバーとして使用して、syslog メッセージを受け入れていました。syslog メッセージ ジェネレーターに使用するコードは次のとおりです。

openlog ("MyProgram", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL0);
cout << "opened the log" << endl;
for (int i = 0 ; i < 10 ; i++) 
{
    syslog (LOG_INFO, "Program started by User %d \n", getuid ());
    syslog (LOG_WARNING, "Beware of the WARNING! \n");
    syslog (LOG_ERR, "fatal ERROR! \n");
}   
closelog ();
cout << "closed the log" << endl;

rsyslog.conf ファイルのエントリを使用して、すべての syslog LOG_LOCAL0 アプリケーション トラフィックが、サーバーがリッスンしている関連する TCP ポートに送信されるようにします。どういうわけか、syslog では、複数の接続ではなく、1 つの接続のみを確立できます。したがって、1 つのスレッドで 1 つの接続のみを使用していました。その接続が閉じられた場合、新しい接続が作成されます。

通常の tcp クライアントで確認しました。これは正常に機能し、受け入れられた接続ごとに複数のスレッドが生成されます。

于 2012-10-22T17:14:15.537 に答える