使用socketpair创建双向通信管道的简明教程

作者:云浮麻将开发公司 阅读:32 次 发布时间:2025-05-25 20:21:31

摘要:在Linux系统中,socketpair是一种创建双向通信管道的机制,它可以为进程之间的通信提供一种相对简单的方式。本文将介绍socketpair的用途、语法、使用限制以及一些实例应用。1. socketpair的用途相信不少读者都已经知道,pipe可以用来在进程之间传输数据,但是,pipe有些限制,...

在Linux系统中,socketpair是一种创建双向通信管道的机制,它可以为进程之间的通信提供一种相对简单的方式。本文将介绍socketpair的用途、语法、使用限制以及一些实例应用。

使用socketpair创建双向通信管道的简明教程

1. socketpair的用途

相信不少读者都已经知道,pipe可以用来在进程之间传输数据,但是,pipe有些限制,比如只能单向传输数据,不能同时读写,只能用于父子进程之间通信等。而socketpair这种机制则是pipe的一个改进版,它支持双向通信,可以同时读写,也可以用于任意两个进程之间通信等。

2. socketpair的语法

socketpair的语法非常简单,可以在C语言、C++、Java等多种语言中使用。

在C语言中,可以使用以下函数创建一个socketpair:

int socketpair(int domain, int type, int protocol, int sv[2]);

参数说明:

- domain:协议族,通常为AF_UNIX或AF_INET。

- type:socket类型,通常为SOCK_STREAM或SOCK_DGRAM。

- protocol:协议,通常为0。

- sv:指向一个保存socket文件描述符的数组,其中index为0的socket表示读端,index为1的socket表示写端。

3. socketpair的使用限制

虽然socketpair是pipe的改进版,但是它也有一些使用限制,需要开发者注意。

- 只能用于同一个主机上的进程通信,而不能用于跨主机通信。

- 双向通信需要两个socket连接,因此socketpair只能用于两个进程之间通信。

- 在传输中需要使用自定义协议,因此程序开发中需要编写更多的代码。

4. socketpair实例

下面我们来看两个简单的socketpair实例。

4.1. 实例1:简单Echo服务器

我们先来看如何使用socketpair实现一个简单的Echo服务器,该服务器接收客户端的输入后,将其返回给客户端。

服务端代码:

#include

#include

#include

#include

#include

#include

#define PORT 9999

int main(int argc, char *argv[])

{

int server_fd, client_fd;

struct sockaddr_in server_addr, client_addr;

socklen_t client_len;

int t, len;

char buf[1024];

if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

perror("socket");

exit(1);

}

memset(&server_addr, 0, sizeof(struct sockaddr_in));

server_addr.sin_family = AF_INET;

server_addr.sin_port = htons(PORT);

server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(server_fd, (struct sockaddr *)&server_addr,

sizeof(server_addr)) == -1) {

perror("bind");

exit(1);

}

if (listen(server_fd, 5) == -1) {

perror("listen");

exit(1);

}

printf("server listening on port %d...\n", PORT);

client_len = sizeof(client_addr);

if ((client_fd = accept(server_fd,

(struct sockaddr *)&client_addr, &client_len)) == -1) {

perror("accept");

exit(1);

}

printf("Accepted connection from %s, port %d\n",

inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

if (socketpair(PF_UNIX, SOCK_STREAM, 0, &t) != 0) {

perror("socketpair");

exit(1);

}

if (fork() == 0) {

close(client_fd);

while ((len = recv(t, buf, 1024, 0)) > 0) {

if (send(t, buf, len, 0) != len) {

perror("send");

exit(1);

}

}

exit(0);

}

close(t);

while ((len = recv(client_fd, buf, 1024, 0)) > 0) {

if (send(client_fd, buf, len, 0) != len) {

perror("send");

exit(1);

}

if (send(t, buf, len, 0) != len) {

perror("send");

exit(1);

}

}

close(client_fd);

return 0;

}

客户端代码:

#include

#include

#include

#include

#include

#include

#define PORT 9999

int main(int argc, char *argv[])

{

int fd;

struct sockaddr_in server_addr;

char buf[1024];

if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

perror("socket");

exit(1);

}

memset(&server_addr, 0, sizeof(struct sockaddr_in));

server_addr.sin_family = AF_INET;

server_addr.sin_port = htons(PORT);

inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);

if (connect(fd, (struct sockaddr *)&server_addr,

sizeof(server_addr)) == -1) {

perror("connect");

exit(1);

}

printf("Type your message: ");

while (fgets(buf, sizeof(buf), stdin)) {

if (send(fd, buf, strlen(buf), 0) != strlen(buf)) {

perror("send");

exit(1);

}

memset(buf, 0, sizeof(buf));

int len = recv(fd, buf, 1024, 0);

if (len < 0) {

perror("recv");

exit(1);

}

printf("%s", buf);

}

return 0;

}

运行结果:

$ ./server

server listening on port 9999...

Accepted connection from 127.0.0.1, port 45660

$ ./client

Type your message: Hello world!

Hello world!

4.2. 实例2:使用socketpair实现多进程通信

我们再来看一个更复杂的例子,该例子使用socketpair实现了多个进程之间的通信,其中两个父进程分别与两个子进程通信,将消息传递下去。

这里需要先解释一下代码中的一些术语:

- ID:每个进程都有一个唯一的ID,用于标识进程。

- pipe_in:向该pipe写入消息,可以通过pipe_out来读取。

- pipe_out:从该pipe读取消息,可以通过pipe_in来写入。

代码:

#include

#include

#include

#include

#include

#include

#include

#define PARENT_A 1

#define PARENT_B 2

#define CHILD_A 3

#define CHILD_B 4

#define PARENT_A_PIPE_IN 0

#define PARENT_A_PIPE_OUT 1

#define PARENT_B_PIPE_IN 2

#define PARENT_B_PIPE_OUT 3

#define CHILD_A_PIPE_IN 4

#define CHILD_A_PIPE_OUT 5

#define CHILD_B_PIPE_IN 6

#define CHILD_B_PIPE_OUT 7

void send_message(int pid, int pipe_in, char *message) {

int len = strlen(message) + 1;

write(pipe_in, &pid, sizeof(int));

write(pipe_in, &len, sizeof(int));

write(pipe_in, message, len);

}

void read_message(int *pid, int pipe_out, char *message) {

int len;

read(pipe_out, pid, sizeof(int));

read(pipe_out, &len, sizeof(int));

read(pipe_out, message, len);

}

void parent_a(int pipe_in, int pipe_out) {

char buffer[1024];

memset(buffer, 0, sizeof(buffer));

read_message(NULL, pipe_out, buffer);

printf("Parent_A received: %s\n", buffer);

send_message(CHILD_A, pipe_in, buffer);

}

void parent_b(int pipe_in, int pipe_out) {

char buffer[1024];

memset(buffer, 0, sizeof(buffer));

read_message(NULL, pipe_out, buffer);

printf("Parent_B received: %s\n", buffer);

send_message(CHILD_B, pipe_in, buffer);

}

void child_a(int pipe_in, int pipe_out) {

char buffer[1024];

memset(buffer, 0, sizeof(buffer));

read_message(NULL, pipe_out, buffer);

printf("Child_A received: %s\n", buffer);

send_message(PARENT_B, pipe_in, buffer);

}

void child_b(int pipe_in, int pipe_out) {

char buffer[1024];

memset(buffer, 0, sizeof(buffer));

read_message(NULL, pipe_out, buffer);

printf("Child_B received: %s\n", buffer);

send_message(PARENT_A, pipe_in, buffer);

}

int main(int argc, char *argv[]) {

int pid;

int pipes[8];

char buffer[1024];

pid_t child_pid;

if (socketpair(AF_UNIX, SOCK_STREAM, 0, &pipes[PARENT_A_PIPE_IN]) != 0) {

perror("socketpair");

exit(1);

}

if (socketpair(AF_UNIX, SOCK_STREAM, 0, &pipes[PARENT_B_PIPE_IN]) != 0) {

perror("socketpair");

exit(1);

}

if (socketpair(AF_UNIX, SOCK_STREAM, 0, &pipes[CHILD_A_PIPE_IN]) != 0) {

perror("socketpair");

exit(1);

}

if (socketpair(AF_UNIX, SOCK_STREAM, 0, &pipes[CHILD_B_PIPE_IN]) != 0) {

perror("socketpair");

exit(1);

}

child_pid = fork();

if (child_pid == 0) {

close(pipes[PARENT_A_PIPE_IN]);

close(pipes[PARENT_B_PIPE_IN]);

parent_a(pipes[CHILD_A_PIPE_OUT], pipes[CHILD_A_PIPE_IN]);

exit(0);

}

child_pid = fork();

if (child_pid == 0) {

close(pipes[PARENT_A_PIPE_IN]);

close(pipes[PARENT_B_PIPE_IN]);

parent_b(pipes[CHILD_B_PIPE_OUT], pipes[CHILD_B_PIPE_IN]);

exit(0);

}

child_pid = fork();

if (child_pid == 0) {

close(pipes[PARENT_A_PIPE_IN]);

close(pipes[PARENT_B_PIPE_IN]);

close(pipes[CHILD_B_PIPE_IN]);

close(pipes[CHILD_B_PIPE_OUT]);

child_a(pipes[CHILD_A_PIPE_OUT], pipes[CHILD_A_PIPE_IN]);

exit(0);

}

child_pid = fork();

if (child_pid == 0) {

close(pipes[PARENT_A_PIPE_IN]);

close(pipes[PARENT_B_PIPE_IN]);

close(pipes[CHILD_A_PIPE_IN]);

close(pipes[CHILD_A_PIPE_OUT]);

child_b(pipes[CHILD_B_PIPE_OUT], pipes[CHILD_B_PIPE_IN]);

exit(0);

}

close(pipes[CHILD_A_PIPE_IN]);

close(pipes[CHILD_B_PIPE_IN]);

close(pipes[CHILD_A_PIPE_OUT]);

close(pipes[CHILD_B_PIPE_OUT]);

memset(buffer, 0, sizeof(buffer));

send_message(PARENT_A, pipes[PARENT_A_PIPE_IN], "Hello, World!");

read_message(&pid, pipes[PARENT_A_PIPE_OUT], buffer);

printf("Parent received message from %d: %s\n", pid, buffer);

memset(buffer, 0, sizeof(buffer));

send_message(PARENT_B, pipes[PARENT_B_PIPE_IN], "How are you?");

read_message(&pid, pipes[PARENT_B_PIPE_OUT], buffer);

printf("Parent received message from %d: %s\n", pid, buffer);

wait(NULL);

wait(NULL);

wait(NULL);

wait(NULL);

return 0;

}

运行结果:

$ ./test

Parent_A received: Hello, World!

Child_A received: Hello, World!

Child_B received: Hello, World!

Parent received message from 3: Hello, World!

Parent_B received: How are you?

Child_A received: How are you?

Child_B received: How are you?

Parent received message from 4: How are you?

  • 原标题:使用socketpair创建双向通信管道的简明教程

  • 本文链接:https://qipaikaifa.cn/qpzx/3789.html

  • 本文由云浮麻将开发公司中天华智网小编,整理排版发布,转载请注明出处。部分文章图片来源于网络,如有侵权,请与中天华智网联系删除。
  • 微信二维码

    ZTHZ2028

    长按复制微信号,添加好友

    微信联系

    在线咨询

    点击这里给我发消息QQ客服专员


    点击这里给我发消息电话客服专员


    在线咨询

    免费通话


    24h咨询☎️:157-1842-0347


    🔺🔺 棋牌游戏开发24H咨询电话 🔺🔺

    免费通话
    返回顶部