1

現在、読み取り/書き込みの基本機能のみを備えた単純なクライアント サーバー プログラムを実装しています。

ただし、たとえば、サーバーがクライアントに応答するために write() を呼び出し、クライアントに対応する read() 関数がない場合、サーバー プログラムはそこでハングすることに気付きました。

現在、単純なタイマーを使用してタイムアウトカウントを定義し、特定のカウント後にクライアントを切断することを考えていますが、そのようなエラーを処理するよりエレガントな/または標準的な方法があるかどうか疑問に思っていますか?

4

2 に答える 2

3

サーバーのブロックを回避し、単一のサーバー インスタンスで複数のクライアントを処理するには、次の 2 つの一般的な方法があります。

  • POSIX スレッドを使用して、各クライアントの接続を処理します。エラーのあるクライアントが原因で 1 つのスレッドがブロックされた場合でも、他のスレッドは引き続き実行されます。リモート クライアントが消えたばかりの場合 (クラッシュ、ネットワーク ダウンなど)、遅かれ早かれ TCP スタックはタイムアウトを通知し、ブロックされたwrite操作はエラーで失敗します。
  • select(2)や などのポーリング メカニズムと一緒にノンブロッキング I/O を使用しpoll(2)ます。ただし、ポーリング呼び出しを使用してプログラムするのは非常に困難です。ネットワーク ソケットは を使用してノンブロッキングfcntl(2)になり、通常write(2)またはread(2)ソケット上でブロックされる場合は、EAGAIN代わりにエラーが返されます。select(2)orを使用poll(2)して、調整可能なタイムアウト期間でソケットで何かが発生するのを待つことができます。たとえば、ソケットが書き込み可能になるのを待つということは、ソケット送信バッファ スペースが十分にあるときに通知されることを意味します。たとえば、以前に書き込まれたデータがクライアント マシンの TCP スタックにフラッシュされた場合などです。
于 2012-06-25T12:14:05.350 に答える
1

クライアント側がソケットから読み取らない場合は、 でソケットを閉じる必要がありますclose。また、クライアントがまだソケットに書き込みたい可能性があるためにそれを行いたくない場合は、少なくとも読み取り半分を で閉じる必要がありますshutdown(fd, SHUT_RD)

EPIPEこれにより、サーバーが書き込み呼び出しを取得するように設定されます。

クライアントを制御しない場合...作成していないランダムなクライアントが接続できる場合、サーバーは悪意のあるクライアントを積極的に処理する必要があります。クライアントが悪意のある方法の 1 つは、サーバーを強制的にハングさせようとすることです。これが起こらないようにするには、ノンブロッキング ソケットと説明したタイムアウト メカニズムを組み合わせて使用​​する必要があります。

一般に、サーバーとクライアントが通信する方法のプロトコルを作成して、相手側が読み取らないときにサーバーもクライアントもソケットに書き込もうとしないようにする必要があります。これは、それらを厳密に同期する必要があるという意味ではありません。しかし、たとえば、HTTP は、プロトコルの任意の時点で相手側が何かを書き込むことを本当に期待しているかどうかについて、どちらの側にも明確にわかるような方法で定義されています。

于 2012-06-25T11:14:34.993 に答える