socketpair是linux提供的一种双向通讯机制,它通过socket实现双向通讯。socketpair本身虽然实现了双向通讯的功能,但是也存在一些限制:比如只能在一个进程的线程之间进行双向通讯或者是在具有亲缘关系的进程间进行通讯。所以socketpair很少情况下会单独使用,它往往需要和其他编程机制结合起来使用才能发挥它真正的作用。本文举两个小例子来说明一下socketpair的基本用法。


一、在一个进程的线程间实现双向通讯

这个例子实现的功能是:编写一个具有两个线程的应用程序,让主线程和子线程通过socketpair进行双向通讯。完整的代码实现如下:

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

/* 定义socketpair缓冲区的大小 */
#define SOCKET_BUFFER_SIZE 		((32) * (1024))

#define BUFFER_SIZE		(256)	// 定义一个缓冲区的大小

/*
 *	定义子线程的主体函数
 */
static void *thread_run_func (void *arg)
{
	int thread_fd = (int)arg;
	char thread_buf[BUFFER_SIZE] = {0};
	int readlen;

	/* a、向主进程发送一个消息 */
	printf("(1) send to main thread : %s\n", "Hello,world!");
	write(thread_fd, "Hello,world!", sizeof("Hello,world!"));

	/* d、接收主进程发送的消息 */
	readlen = read(thread_fd, thread_buf, BUFFER_SIZE);
	thread_buf[readlen] = '\0';
	printf("(4) recv from main thread : %s\n", thread_buf);
}


/*	
 *	定义一个子线程,实现两个进程间的双向通讯
 */
int main(int argc, char *argv[])
{
	int sockets[2];
	int result;
	int bufferSize;

	pthread_t thread;

	char main_buf[BUFFER_SIZE]= {0};
	int readlen;

	/* 创建一个socketpair双向通讯的实例 */
	result = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets);
	if(-1 == result)
	{
		printf("socketpair error!\n");
		return -1;
	}

	/* 设置socketpair双向通讯各个缓冲区 */
	bufferSize = SOCKET_BUFFER_SIZE;
	setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));

	/* 创建一个子线程用于和主线程之间进行双向通讯 */
	result = pthread_create(&thread, NULL, thread_run_func, (void *)sockets[1]);

	sleep(1);	/* 延时一段时间让子进程先于主进程运行 */

	/* b、接收子进程发送过来的消息 */
	readlen = read(sockets[0], main_buf, BUFFER_SIZE);
	main_buf[readlen] = '\0';
	printf("(2) recv from child thread : %s\n", main_buf);

	/* c、发送一个消息给子进程 */
	printf("(3) send to child thread : %s\n", "TECH-PRO");
	write(sockets[0], "TECH-PRO", sizeof("TECH-PRO"));

	sleep(1);	/* 延时一段等待子进程执行完毕 */

	return 0;
}


编译并运行,结果如下:


grpc双向通信 javascript 双向通信功能_子进程



二、在父子进程间实现双向通讯

这个例子实现的功能是:编写一个应用程序,实现两个进程,让这两个进程之间实现双向通讯。完整代码如下所示:

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

/* 定义socketpair缓冲区的大小 */
#define SOCKET_BUFFER_SIZE 		((32) * (1024))

#define BUFFER_SIZE		(256)	// 定义一个缓冲区的大小

/*	
 *	定义一个子线程,实现两个进程间的双向通讯
 */
int main(int argc, char *argv[])
{
	int sockets[2];
	int result;
	int bufferSize;

	pthread_t thread;

	char buf[BUFFER_SIZE]= {0};
	int readlen;

	int father_fd;
	int child_fd;

	/* 创建一个socketpair双向通讯的实例 */
	result = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets);
	if(-1 == result)
	{
		printf("socketpair error!\n");
		return -1;
	}

	/* 设置socketpair双向通讯各个缓冲区 */
	bufferSize = SOCKET_BUFFER_SIZE;
	setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));

	father_fd = sockets[0];
	child_fd = sockets[1];

	/* 创建子进程 */
	result = fork();
	if(-1 == result)
	{
		printf("fork error!\n");
		return -1;
	}
	else if(0 == result)	// 子进程
	{
		/* a、向主进程发送一个消息 */
		printf("(1) send to main thread : %s\n", "Hello,world!");
		write(child_fd, "Hello,world!", sizeof("Hello,world!"));

		/* d、接收主进程发送的消息 */
		readlen = read(child_fd, buf, BUFFER_SIZE);
		buf[readlen] = '\0';
		printf("(4) recv from main thread : %s\n", buf);
	}
	else if(result > 0)		// 父进程
	{
		sleep(1);	/* 延时一段时间让子进程先于主进程运行 */

		/* b、接收子进程发送过来的消息 */
		readlen = read(father_fd, buf, BUFFER_SIZE);
		buf[readlen] = '\0';
		printf("(2) recv from child thread : %s\n", buf);

		/* c、发送一个消息给子进程 */
		printf("(3) send to child thread : %s\n", "TECH-PRO");
		write(father_fd, "TECH-PRO", sizeof("TECH-PRO"));

		sleep(1);	/* 延时一段等待子进程执行完毕 */
	}

	return 0;
}


编译并运行,结果如下所示:

grpc双向通信 javascript 双向通信功能_linux_02


至此,两个简单的socketpair的小例子实现完毕。本人能力有限,文中有错误或者不合理的地方,请多指教。