38

我在同一个系统上有 2 个应用程序需要来回通信。根据我的研究,我相信这称为进程间通信,使用 socketpair() 是解决我的问题的最佳方法。

我正在(字面上)试图开始在 C 中使用 socketpair() 创建套接字。据我了解,套接字是一个非常复杂的主题,而我作为一个新手 C 程序员肯定无济于事。

我在过去的 48 小时内搜索过,阅读教程等,但我仍然无法得到它。我理解这个概念,但代码太混乱了。我已经读过这篇文章了几次:http ://beej.us/guide/bgnet/html/single/bgnet.html ,但这还不够简单。

有人可以提供一些示例(如此简单的五年级学生可以理解)或指向一个好的教程吗?

4

4 回答 4

71

socketpair只能在创建两个进程的地方使用,如下所示:

  1. call socketpair- 现在你有两个套接字文件描述符(单个管道的两端)
    • 指定一端为父端,另一端为端。无所谓,做个选择,以后坚持
  2. 呼叫fork- 现在您有两个进程
    1. 如果fork返回零,你就是孩子。关闭文件描述符,保留描述符,并将其用作该进程的管道末端
    2. 如果fork返回非零,则您是父级。关闭文件描述符,保留文件描述符并将其用作管道的末端
  3. 您现在有两个进程,每个进程都有一个文件描述符,代表同一管道的不同端。请注意,两个进程都在运行同一个程序,但在调用fork. 如果级调用write其套接字,则级将能够从其套接字读取该数据,反之亦然

这是直接翻译成代码:

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 */
}

请注意,这只是示例代码:我省略了所有错误检查和合理的流协议。


如果您希望两个单独的程序进行通信(例如,您有一个名为client的可执行文件,一个名为server的可执行文件),则不能使用此机制。相反,您可以:

  • 使用 UNIX 套接字(其中一台主机上的 IPC 管道由文件名标识 - 仅当客户端服务器在同一台机器上运行时才有效)
  • 或使用 TCP/IP 套接字(IP 地址和端口标识管道,客户端服务器可以在不同的机器上)

如果您并不特别需要套接字,并且很乐意要求客户端服务器在同一台机器上运行,那么您也可以使用共享内存或消息队列。

于 2012-07-12T21:54:56.190 回答
8

socketpair创建一对匿名套接字,通常是 unix/local 套接字,它们仅用于父进程和子进程之间的通信,或者在需要使用它们的进程可以从共同祖先继承文件描述符的其他情况下。

如果您要在不相关的(从亲子关系的意义上)进程之间进行通信,则需要使用socketbindconnect在一个进程中创建一个侦听套接字,并在另一个进程中创建一个客户端套接字以连接到它。

于 2012-07-12T21:47:41.060 回答
1

对于两个进程之间的通信,是的,进程间通信或 IPC 是您应该寻找的。套接字只是通信方法之一,如果您必须实现一对多连接,它会很有用。意味着,一个服务器进程以请求-响应方式与许多客户端进程通信。由于您是 IPC 的新手,因此套接字地址和所涉及的细节可能看起来难以掌握是可以理解的。(尽管您会在适当的时候发现它们很容易:-))

对于您的问题,我建议您使用更简单的 IPC 机制,例如 Pipe、FIFO、Message Queue。我不确定您是如何得出使用 socketpair 的结论的。由于您没有提及您需要的设计或 IPC 类型的任何内容,并且基于使用水平,我强烈建议您查看某些书籍或互联网中的 Pipe 或 FIFO 示例代码。它们看起来应该比套接字更容易实现并且工作得更快。

于 2012-07-14T19:25:45.157 回答
-3

使用 TCP/IP。虽然还有其他可用的 IPC 机制(例如 Unix 域套接字和 SYSV IPC),但出于多种原因,您最好使用 TCP/IP。这里有一些:

  1. 网上有很多教程和其他信息描述了如何进行 TCP/IP
  2. 现代系统,尤其是 Linux 和 *BSD,与 Unix 域套接字甚至 SYSV IPC 相比,没有对使用 TCP/IP 施加重大损失。
  3. 您可以将许多库和框架用于通过 TCP/IP 进行通信的应用程序。

我不会使用 TCP/IP 在两个“程序”之间进行通信的唯一情况是它们实际上是线程而不是单独的程序。

于 2012-07-12T21:48:40.023 回答