0

C 言語で複数 (1000 以上) のクライアント接続を同時に処理できるサーバーを作成しようとしています。すべての接続は、次の 3 つのことを達成するためのものです。

  1. サーバーにデータを送信する
  2. サーバーはデータを処理します
  3. サーバーがクライアントにデータを返す

すべての接続を処理するためにノンブロッキング ソケットと epoll() を使用していますが、サーバーが 1 つのクライアントからデータを受信した直後に問題が発生し、その前にデータの処理に数秒かかる関数を呼び出す必要があります。接続を閉じる前にクライアントに送り返す必要がある結果を返します。

私の質問は、1 つのクライアントのデータが「調理中」のときに、より多くの接続を処理し続けるために、どのパラダイムを使用できるかということです。

コンピューティング関数を呼び出す必要があるたびにスレッドまたはプロセスを作成することでそれを行う可能性について少し調査してきましたが、可能な同時接続の数を考えるとこれが可能かどうかはわかりません.なぜ私がここに来たのは、この問題で私が無知であることに光を当てることができる誰かがより経験豊富であることを期待していたからです.


コードスニペット:

while (1)
                {
                  ssize_t count;
                  char buf[512];
                  count = read (events[i].data.fd, buf, sizeof buf); // read the data
                  if (count == -1)
                    {
                      /* If errno == EAGAIN, that means we have read all
                         data. So go back to the main loop. */
                      if (errno != EAGAIN)
                        {
                          perror ("read");
                          done = 1;
                        }
                      /* Here is where I should call the processing function before
                         exiting the loop and closing the actual connection */

                         answer = proc_function(buf);
                         count = write (events[i].data.fd, answer, sizeof answer); // send the answer to the client
                         break;
                    }
                    ...

前もって感謝します。

4

1 に答える 1

1

これを達成するには、ある程度マルチスレッドまたはマルチプロセスが賢明なようです。マルチスレッドまたはマルチプロセスの程度が問題です。

1) ポーリング システムを完全にダンプし、接続ごとにスレッド/プロセスを使用できます。そのスレッドは、その接続の処理に取り組んでいる限り、ストールする可能性があります。次に、毎回スレッド/プロセスを作成/強制終了するか (おそらく最も簡単)、スレッド/プロセスのプールを用意するか (おそらく最速) を決定する必要があります。

2)ネットワークビット用のスレッド/プロセスを用意し、処理を別のスレッドに渡すことができます。これはあまり並列ではありませんが、作業のリストを切り刻んでいる間、少なくともネットワーク接続を処理し続けることができることを意味します。これにより、少なくともどの処理が処理されているかを制御できます。この方法で受信接続に優先順位を付けるのは簡単ですが、オプション 1 はそうではないかもしれません。

3)(可能な1と2の並べ替え)非同期I / Oを使用して接続を多重化できます。上記の 1 & 2 と同じ方法で処理を処理する必要があります。

また、スレッドとプロセスの問題もあります。スレッドはおそらくより迅速に開始できますが、データの整合性を確保するのはより困難です。プロセスの回復力は向上しますが、プロセス間のインターフェースを強化する必要があります。

また、スレッド/プロセス間でデータを渡す方法も決定する必要があります。オプション 1 では、接続をスレッドに渡すだけでよいため、これはそれほど問題ではありません。オプション 2 は (データの内容によっては) もっと問題になる可能性があります。メッセージを渡すためにメッセージキューを使用できますが、共有メモリを送信するデータが多い場合は、より適切です。共有メモリは、プロセスを設計するのは面倒ですが、スレッドでは簡単です (すべてのスレッドが同じメモリ空間を共有するため)。

このスケールに到達すると、パフォーマンスの問題も発生します。これらのパフォーマンス特性を調査する価値があります。select や poll などの呼び出しのスケールの違いは、多数の接続を処理している場合に重要になります。

どのようなデータが送受信されているかを知らなければ、確かな推奨事項を提示することは困難です。

ちなみに、これは新しい問題ではありません。Dan Kegelは、数年前にそれについて良い記事を書いていました。現在は古くなっていますが、概要はまだ良好です。ただし、彼が議論する概念については、現在の最新技術を調査する必要があります。

于 2013-07-10T14:49:37.450 に答える