0

しばらくの間、C コーダーをしています - 初心者でも専門家でもありません。今、私は PPC Linux 上の C で特定のデーモン化されたアプリケーションを持っています。PHP の socket_connect をクライアントとして使用して、このサービスにローカルで接続します。サーバーは、Unix ソケット経由で接続を多重化するために epoll を使用します。ユーザーが送信した文字列は、strstr() を使用して特定の文字/単語について解析され、見つかった場合は、4 つの結合可能なスレッドを異なる Web サイトに同時に生成します。ソケット、接続、書き込み、読み取りを使用して、各スレッドのポート 80 で TCP 経由で前述の Web サーバーと対話します。すべての接続と書き込みは成功したようです。ただし、Web サーバー ソケットへの読み取りは失敗します。(A) 3 つのスレッドすべてがハングしたように見え、1 つのスレッドだけが -1 を返し、errno が 104 に設定されます。応答するスレッドには 10 分ほどかかります。 104(EINTRですか?)、これは、ネットワーク コンテキストでは、「接続がピアによってリセットされた」ことを示唆しています。または (B) 3 つのスレッドから 0 バイトで、4 つのスレッドのうち 1 つだけが実際にデータを返します。ソケットは読み取り/書き込みスレッドセーフではありませんか? 私は、strtok_r、gethostbyname_r などのスレッドセーフ (および再入可能) libc 関数を使用しています。

*シングルスレッドのスタンドアロン(他のすべてが等しい)を実行すると、すべてが完全に正しく機能しますが、もちろん直列では並列ではないため、上記のWebホストが実際に接続をリセットしているとは思えません。

2 番目の問題もあります (おっと)、epoll された Unix ソケットに接続しているクライアントに書き戻すことができません。デーモン アプリケーションがハングし、CPU を 100% 以上占有します。それでも、クライアント側には何も書き込まれません。これが発生するたびに、クライアント(非常に典型的なPHPソケットアプリケーション)が接続を閉じていないことを確認してください-エラーも検出されませんでした。何か案は?

Valgrind、GDB、または多くのロギングを使用しても、何が問題なのかわかりません。親切にできるところを手伝ってください。

4

2 に答える 2

0

10分後にECONNRESETを取得すると、接続がタイムアウトした結果のように聞こえます。ウェブサーバーがデータを送信していないか、アプリがデータを受信して​​いません。

前者をテストするには、Wiresharkなどのプログラムをローカルループバックデバイスに接続し、使用しているポートとの間のトラフィックを探します。

後で、epoll()のマニュアルページを見てください。彼らは、エッジトリガーイベントを使用すると、バッファーにデータが残っているためにロックアップが発生する可能性があるが、新しいデータが入らないため、新しいイベントがトリガーされないシナリオについて言及しています。

于 2010-04-26T23:05:04.203 に答える
0

はい、読み取り/書き込みはスレッドセーフです。ただし、gethostbyname()とgetservbyname()を使用している場合は注意してください。これらは静的データへのポインターを返し、スレッドセーフではない可能性があります。

errno 104はECONNREFUSEDです(EINTRではありません)。strerrorまたはperrorを使用して、特定のerrnoコードのテキストエラーメッセージ(「ピアによる接続のリセット」など)を取得します。

何が問題になっているのかを把握する最良の方法は、多くの場合、非常に詳細なログ記録を行うことです。すべての操作の結果に加えて、接続先のIPアドレス/ポート、読み取り/書き込みバイト数、スレッドIDなどの詳細をログに記録します。 。そしてもちろん、ロギングコードがスレッドセーフであることを確認してください:-)

于 2010-04-06T04:58:21.883 に答える