23

私は、特にソケットを使用したCでのイベント駆動型プログラミングに非常に興味があるので、研究に時間を割くつもりです。

クライアント/サーバーアプリのように、ファイルとネットワークのI / Oが多いプログラムを作成したいとします。基本的に、最初の質問は、このモデルの背後にある哲学です。通常のプログラミングでは新しいプロセスを生成しますが、どうして1つのプロセスで他の多くの要求を実際に処理できるのでしょうか。たとえば、スレッドや他のプロセスを作成せずに接続を処理できるWebサーバーがいくつかあり、メインプロセスは1つだけです。

これは複雑ですが、さまざまなソリューションがどのように機能するかを知ることは常に素晴らしいことです。

4

5 に答える 5

21

あなたは間違いなく以下を読む必要があります:http ://www.kegel.com/c10k.html 。このページは、イベント駆動型および非同期技術の完全な概要です。

ただし、迅速で汚い答え:イベント駆動型は非ブロッキングでも非同期でもありません。

イベント駆動型とは、プロセスがファイル記述子(およびソケット)を監視し、ある記述子で何らかのイベントが発生した場合にのみ動作することを意味します(イベントは、データの受信、エラー、書き込み可能になりました...)。

BSDソケットには「select()」関数があります。呼び出されると、OSは記述子を監視し、記述子の1つで何らかのイベントが発生するとすぐにプロセスに戻ります。

ただし、上記のWebサイトには、はるかに優れた説明(およびさまざまなAPIの詳細)があります。

于 2012-06-16T12:26:36.863 に答える
3

「このモデルの背後にある哲学は何ですか」

イベントドリブンとは、「監視」がないことを意味しますが、イベント自体がアクションを開始します。

通常、これは、外部デバイスからシステムへの信号である割り込み、または(ソフトウェア割り込みの場合)非同期プロセスによって開始されます。

https://en.wikipedia.org/wiki/Interrupt

さらに読むことはここにあるようです:

https://docs.oracle.com/cd/E19455-01/806-1017/6jab5di2m/index.html#sockets-40- 「割り込み駆動型ソケットI/O」

また、 http://cs.baylor.edu/~donahoo/practical/CSockets/textcode.htmlには、割り込み駆動型ソケットの例と、その他のソケットプログラミングの例があります。

于 2016-08-12T21:04:22.323 に答える
1

イベント駆動型プログラミングは、イベントループに基づいています。ループは単に新しいイベントを待機し、イベントを処理するためのコードをディスパッチしてから、ループバックして次のイベントを待機します。ソケットの場合、あなたは「非同期ネットワークプログラミング」について話している。これには、select ()またはKqueue ()などの他のオプションが含まれ、イベントループ内のイベントを待機します。ソケットは非ブロッキングに設定する必要があります。これにより、read()またはwrite()時に、コードがI/Oの完了を待機しなくなります。

非同期ネットワークプログラミングは非常に複雑で、正しく行うのが難しい場合があります。ここここでいくつかの紹介をチェックしてください。これを正しく行うには、 libeventliboopなどのライブラリを使用することを強くお勧めします。

于 2012-06-16T12:30:10.157 に答える
1

この種のTCPサーバー/クライアントは、select(2)呼び出しソケットと非ブロッキングソケットを使用して実装できます。

ブロッキングソケットよりも非ブロッキングソケットを使用する方が注意が必要です。

例:

connect通常、呼び出しはすぐに-1を返しEINPROGRESS、非ブロッキングソケットが使用されている場合はerrnoを設定します。この場合select、接続が開かれるか失敗するまで待機するためにを使用する必要があります。connect0を返す場合もあります。これは、ローカルホストへの接続を作成した場合に発生する可能性があります。このようにして、1つのソケットがTCP接続を開いている間に、他のソケットにサービスを提供できます。

于 2012-06-20T10:13:36.660 に答える
0

それがどのように機能するかについては、実際には非常にプラットフォーム固有です。

Linuxシステムで実行している場合は、それほど難しくはありませんが、「フォーク」を使用してプロセスのコピーを生成するだけで、次のようなトリックが実行されます。

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet.h>
#include <signal.h>
#include <unistd.h>

int main()
{
  int server_sockfd, client_sockfd;
  int server_len, client_len;
  struct sockaddr_in server_address;
  struct sockaddr_in client_address;

  server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

  server_address.sin_family = AF_INET;
  server_address.sin_addr.s_addr = htonl(INADDR_ANY);
  server_Address.sin_port = htons(1234);
  server_len = sizeof(server_address);
  bind(server_sockfd, (struct sockaddr *)&server_address, server_len);

  listen(server_sockfd, 5);

  signal(SIGCHLD, SIG_IGN);

  while(1)
  {
    char ch;
    printf("Server Waiting\n");
    client_len = sizeof(client_address);
    client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len)

    // Here's where we do the forking, if you've forked already then this will be the child running, if not then your still the parent task.

    if(fork() == 0)
    {
      // Do what ever the child needs to do with the connected client
      read(client_sockfd, &ch, 1);
      sleep(5); // just for show :-)
      ch++;
      write(client_sockfd, &ch, 1);
      close(client_sockfd);
      exit(0);
    }
    else
    {
      // Parent code here, close and loop for next connection
      close(client_sockfd);
    }
  }
}

テストコンパイルを行うには、現時点ではLinuxボックスの近くにいないので、そのコードを少しいじる必要があるかもしれません。ほとんどメモリから入力しました。

ただし、Linux / UnixベースのシステムのCでこれを行うには、フォークを使用するのが標準的な方法です。

Windowsの下では、これは非常に異なる話であり、必要なすべてのコードを完全に思い出せないものです(最近、C#でのコーディングに慣れています)が、ソケットの設定は、使用する必要があることを除いてほとんど同じです。互換性を高めるための「Winsock」API。

(とにかく)標準のバークレーソケットを窓の下で使用することはできますが、落とし穴や穴がたくさんあります。窓のウィンソックの場合、これは開始するのに適した場所です。

http://tangentsoft.net/wskfaq/

私の知る限り、Winsockを使用している場合は、スポーンとマルチクライアントに役立つものがありますが、私自身は通常、別のスレッドをスピンオフしてソケット接続をコピーしてから、に戻ります。サーバーをリッスンしているループ。

于 2012-06-16T11:13:08.993 に答える