进程同步——Unix域套接字

Unix域套接字

  • 域套接字是一种高级的进程间通信方法
  • Unix域套接字可以用于同一机器进程间通信
  • 套接字(socket)原是网络通信中的术语
  • Unix系统提供的域套接字提供了网络套接字类似的功能
  • 不需要额外的机制保证多个进程间访问的问题

在部署服务的时候Nginx,uWSGI的时候都会使用到域套接字

模拟通信

服务端

  1. 创建套接字
  2. 绑定(bind)套接字
  3. 监听(listen)套接字
  4. 处理和接收信息

使用域套接字,将会在文件系统里面创建一个文件,这个文件连接客户端和服务端

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>

#include <iostream>

// 域套接字
#define SOCKET_PATH "./domainsocket" // 定义路径
#define MSG_SIZE 2048 // 定义信息最大长度

int main()
{
    int socket_fd, accept_fd;
	int ret = 0;
	socklen_t addr_len;
	char msg[MSG_SIZE];
	struct sockaddr_un server_addr;

    // 1. 创建域套接字
	socket_fd = socket(PF_UNIX,SOCK_STREAM,0); // 类别,信息流格式
	// -1创建失败
	if(-1 == socket_fd){
		std::cout << "Socket create failed!" << std::endl;
		return -1;
	}
    // 移除已有域套接字路径
	remove(SOCKET_PATH);
    // 内存区域置0
	bzero(&server_addr,sizeof(server_addr));
	server_addr.sun_family = PF_UNIX;
	strcpy(server_addr.sun_path, SOCKET_PATH);

    // 2. 绑定域套接字
    std::cout << "Binding socket..." << std::endl;
    // 创建的域套接字,服务端地址,服务端大小
	ret = bind(socket_fd,(sockaddr *)&server_addr,sizeof(server_addr));

	if(0 > ret){
		std::cout << "Bind socket failed." << std::endl;
		return -1;
	}
	
    // 3. 监听套接字
    std::cout << "Listening socket..." << std::endl;
	ret = listen(socket_fd, 10);
	if(-1 == ret){
		std::cout << "Listen failed" << std::endl;
		return -1;
	}
    std::cout << "Waiting for new requests." << std::endl;
    accept_fd = accept(socket_fd, NULL, NULL);
    
    bzero(msg,MSG_SIZE);

    while(true){
        // 4. 接收&处理信息
        recv(accept_fd, msg, MSG_SIZE, 0);
        std::cout << "Received message from remote: " << msg <<std::endl;
    }

    close(accept_fd);
	close(socket_fd);
	return 0;
}

客户端

  1. 创建套接字
  2. 连接套接字
  3. 发送信息
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>

#include <iostream>

#define SOCKET_PATH "./domainsocket"
#define MSG_SIZE 2048

int main()
{
    int socket_fd;
	int ret = 0;
	char msg[MSG_SIZE];
	struct sockaddr_un server_addr;

    // 1. 创建域套接字
	socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
	if(-1 == socket_fd){
		std::cout << "Socket create failed!" << std::endl;
		return -1;
	}
    
    // 内存区域置0
	bzero(&server_addr,sizeof(server_addr));
	server_addr.sun_family = PF_UNIX;
	strcpy(server_addr.sun_path, SOCKET_PATH);

    // 2. 连接域套接字
	ret = connect(socket_fd, (sockaddr *)&server_addr, sizeof(server_addr));

	if(-1 == ret){
		std::cout << "Connect socket failed" << std::endl;
		return -1;
	}

	while(true){
        std::cout << "Input message>>> ";
        fgets(msg, MSG_SIZE, stdin);
		// 3. 发送信息
		ret = send(socket_fd, msg, MSG_SIZE, 0);
	}

	close(socket_fd);
	return 0;
}

域套接字提供的是一种可靠的信息的传递,相比共享内存,不需要维护多个进程读取空间的机制,Unix域套接字相比共享内存多了一些可靠性。client进程与server进程在进行通信时,不需要额外的标记管理同步的机制。Unix域套接字使用比共享内存简单。
如果使用域套接字,会在某一个路径创建socket文件,文件是套接字类型。

  1. 提供单机简单可靠的进程通信服务。
  2. 只能在单机使用,不能跨机器。

猜你喜欢

转载自blog.csdn.net/wankcn/article/details/108430379