0

友人がクライアント側をプログラミングしているときに、C を使用してグループ チャット システムのサーバー側をプログラミングしようとしています。サーバーが受信するクライアント接続ごとに、子プロセスをフォークして、クライアントを処理し、さらにクライアントを受け入れ続けるようにします。

サーバーは、現在接続されている各クライアントにすべてのオンライン ユーザー (接続されているクライアント) のリストを送信する必要があるため、パイプを使用しました。基本的に、子プロセスが作成されると、ソケットを介してクライアントから情報を受け取り、パイプを介してすべてのクライアントのリストを保持している親にその情報を送信します。このリストは、クライアントがチャットの開始や切断などの変更を行うたびに更新する必要があります。たとえば、クライアントが切断された場合、子はパイプを介して親にメッセージを送信し、親はリストが更新されるように必要な操作を行います。新しい接続ごとにパイプが作成されることに注意してください。

私の問題は、たとえば、3 つの接続を次々に受信し、2 番目の子が切断された場合、そのような親は 2 番目の子とは異なるパイプを持っているため、親がパイプから情報を読み取っていないことです。(3 番目の接続が行われたため、新しいパイプが作成されたことを思い出してください)。この問題を解決するにはどうすればよいですか?

また、1 つの共通パイプを作成しようとしましたが、読み取り/書き込みの前にパイプを閉じないとエラーが発生し、それらを閉じると、パイプが閉じられるため、2 番目のクライアントが接続したときにセグメンテーション エラーが発生します。

私は何時間も無駄に探していたので、どんな助けも大歓迎です.

ありがとう。

4

1 に答える 1

0

親サーバー プロセスは、子を作成するため、子がいつ作成されるかを認識します。子が死亡したときに通知されるように、SIGCLD シグナルハンドラーを設定することで、子がいつ死亡したかを知ることができます。N番目の子には、閉じる必要のある N-1 パイプがあります — 他の子に行くパイプ (一部の子が死亡していない限り)。親プロセスは、作成したパイプの書き込み側を閉じます。子プロセスは、継承するパイプの読み取り側を閉じます (これにより、クライアントへのソケットと、親と通信するために作成されたパイプの書き込み側が残ります)。

子がクライアントとの通信を開始するタイミングを知る必要がある場合は、パイプを介して子から親にメッセージを送信する必要があります。子がいつ通信を停止したかを判断する方法はそれほど明白ではありません — 子が再びアイドル状態にあると宣言するまでにどれくらいの時間が必要ですか?

親では、リッスンしているソケットとすべての読み取りパイプで、何らかの形状または形式 ( select()poll()、 ) でポーリングを終了します。epoll()何らかの活動が発生すると、親は目を覚まし、適切に対応します。数千以上のクライアントに拡張する必要がない限り、これは実現可能な設計です。特に十分なファイル記述子を閉じる際には、注意が必要です。

あなたは言う:

私の問題は、たとえば、3 つの接続を次々に受信し、2 番目の子が切断された場合、そのような親は 2 番目の子とは異なるパイプを持っているため、親がパイプから情報を読み取っていないことです。(3 番目の接続が行われたため、新しいパイプが作成されたことを思い出してください)。この問題を解決するにはどうすればよいですか?

親には、パイプの反対側にある子 (PID) を示すとともに、開いているファイル記述子 (さまざまな子への読み取り用に開いているパイプ) の配列が必要です。waitpid()親は、パイプで EOF を取得したとき、または子が死亡したことを (または親族を介して) 通知されたときに、パイプを閉じます。ポーリング メカニズムは、少なくとも間接的に、パイプが閉じられたことを通知します (ファイル記述子がブロックされないことが通知され、その後、EOF — ゼロ バイトの読み取り) が返されます。

あなたのシナリオでは、親は1つのリッスンソケットを開いており、さらに3つの子へのパイプ用の3つの読み取りファイル記述子(さらに標準入力、出力、エラー、およびおそらくsyslog)があります。

すべての子から 1 つのパイプを使用することもできますが、これを処理するのは非常に面倒です。どの子がメッセージ内の各メッセージを書き込んだかを特定して、メッセージが子によってアトミックに書き込まれるようにする必要があります。親は、混乱しないように、いつでもどのくらい読むべきかを伝えることができなければなりません. 単一パイプの利点は、ポーリング システム コールで実行するファイル記述子の操作が少ないことです。また、無期限にスケーリングします (ファイル記述子が不足することはありません)。

どちらの場合も、コア ダンプで問題が発生することはありません。

于 2013-05-26T06:54:30.673 に答える