web-dev-qa-db-ja.com

C / UnixのSocketpair()

同じシステム上に2つのアプリケーションがあり、それらは相互に通信する必要があります。私の研究から、これはプロセス間通信と呼ばれ、socketpair()の使用が私の問題に最適な方法であると信じています。

私は(文字通り)Cでsocketpair()でソケットを作成しようと試みて髪を引き裂いています。私が理解していることから、ソケットは非常に複雑なトピックであり、私は初心者のCプログラマーであることは確かに状況を助けていません。

私は過去48時間Googleで検索し、チュートリアルなどを読みましたが、まだ取得できません。私はこの概念を理解していますが、コードは非常に紛らわしいです。私はこの記事を何度か読みました: http://beej.us/guide/bgnet/html/single/bgnet.html 、しかしそれは十分に単純ではありません。

誰かがいくつかの例を提供することができますか(5年生が理解できるほど簡単です)、または良いチュートリアルを教えてくれますか?

26
NASA Intern

socketpairは、次のように両方のプロセスを作成する場所でのみ使用できます。

  1. call socketpair-2つのソケットファイル記述子(1つのパイプの両端)があります。
    • 片方の端をに、もう片方を端に指定します。どちらでも構いませんが、選択して後でそれに従うだけです
  2. forkを呼び出します-これで2つのプロセスができました
    1. forkがゼロを返した場合、あなたは子供です。 ファイル記述子を閉じ、記述子を保持し、このプロセスのパイプの終わりとして使用します
    2. forkがゼロ以外を返した場合、あなたは親です。 ファイル記述子を閉じ、を保持し、パイプの終わりとして使用します
  3. これで2つのプロセスができ、それぞれに同じパイプの異なる端を表す1つのファイル記述子があります。両方のプロセスは同じプログラムを実行していますが、forkを呼び出した後、異なるブランチをたどっていることに注意してください。 がそのソケットでwriteを呼び出す場合、itsソケットからそのデータを読み取ることができ、その逆も同様です。

コードへの直接的な変換は次のとおりです。

void child(int socket) {
    const char hello[] = "hello parent, I am child";
    write(socket, hello, sizeof(hello)); /* NB. this includes nul */
    /* go forth and do childish things with this end of the pipe */
}

void parent(int socket) {
    /* do parental things with this end, like reading the child's message */
    char buf[1024];
    int n = read(socket, buf, sizeof(buf));
    printf("parent received '%.*s'\n", n, buf);
}

void socketfork() {
    int fd[2];
    static const int parentsocket = 0;
    static const int childsocket = 1;
    pid_t pid;

    /* 1. call socketpair ... */
    socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);

    /* 2. call fork ... */
    pid = fork();
    if (pid == 0) { /* 2.1 if fork returned zero, you are the child */
        close(fd[parentsocket]); /* Close the parent file descriptor */
        child(fd[childsocket]);
    } else { /* 2.2 ... you are the parent */
        close(fd[childsocket]); /* Close the child file descriptor */
        parent(fd[parentsocket]);
    }
    exit(0); /* do everything in the parent and child functions */
}

これは単なるサンプルコードであることに注意してください。すべてのエラーチェックと適切なストリームプロトコルは省略しています。


2つのseparateプログラムを通信させたい場合(たとえばclientと呼ばれる実行可能ファイルとserverと呼ばれる実行可能ファイルがある場合)は使用できませんこのメカニズム。代わりに、次のことができます。

  • uNIXソケットを使用します(1つのホスト上のIPCパイプはファイル名で識別されます-これはclientおよびserverで実行される場合にのみ機能します同じマシン)
  • または、TCP/IPソケットを使用します(IPアドレスとポートがパイプを識別し、clientserverが異なるマシン上にある場合があります)

具体的にソケットを必要とせず、同じマシンでclientおよびserverを実行する必要がある場合は、以下を実行することもできます。共有メモリまたはメッセージキューを使用します。

56
Useless

socketpairは、匿名ソケットのペアを作成します。通常は、Unix /ローカルソケットであり、親プロセスと子プロセス間の通信、またはそれらを使用する必要があるプロセスでのみ有効です共通の祖先からファイル記述子を継承できます。

無関係な(親子関係の)プロセス間で通信を行う場合は、socketbind、およびconnectを使用してリスニングソケットを作成する必要があります。 1つのプロセスを作成し、他のプロセスで接続するクライアントソケットを作成します。

7
R..

はい、2つのプロセス間で通信するには、プロセス間通信またはIPCを探す必要があります。ソケットは通信方法の1つにすぎず、1対1の実装が必要な場合に便利です。多くの接続。つまり、多くのクライアントプロセスと要求/応答方式で通信する1つのサーバープロセス。IPCの初心者であるため、ソケットアドレスと関連する詳細を把握するのが難しいように見えることは理解できます。それらはやがて簡単に:-))

あなたの問題については、Pipe、FIFO、Message Queueのような単純なIPCメカニズムを使用することをお勧めします。socketpairを使用するという結論に至った理由はわかりません。デザインまたは種類IPC必要ですAND使用レベルに基づいて、パイプまたはFIFOいくつかの本やインターネットのサンプルコードを参照することを強くお勧めします。実装が簡単で、ソケットよりも高速に動作します。

1
Groovy