Skip to content

进程同步之Unix域套接字

  • 套接字(socket)原是网络通信中使用的术语
  • Unix系统提供的域套接字提供了网络套接字类似的功能

服务端使用unix套接字

  1. 创建套接字
  2. 绑定套接字
  3. 监听套接字
  4. 接收 & 处理信息

客户端使用unix套接字

  1. 创建套接字
  2. 连接套接字
  3. 发送消息

unix 套接字缺点

  • 提供了单机简单可靠的进程通信同步服务
  • 只能在单机使用,不能跨机器使用

域套接字的例子

  • 客户端 -> 域套接字 -> 服务端
#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);
    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;
}
#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;
}
export CC=gcc
export CPP=g++
export CFLAGS= -g -lpthread


CSRCS = $(wildcard *.c)  
COBJS = $(patsubst %.c, %, $(CSRCS))  
CPPSRCS = $(wildcard *.cpp)  
CPPOBJS += $(patsubst %.cpp, %, $(CPPSRCS))  


CHEADERS = $(wildcard *.h)  

OBJ = $(COBJS)
OBJ += $(CPPOBJS)

all: $(OBJ)

%:%.c $(CHEADERS)
    $(CC) $^ -o $@ $(CFLAGS)

%:%.cpp $(CHEADERS)
    $(CPP) $^ -o $@ $(CFLAGS)



clean:
    rm *.o $(OBJ)  -rf

.PHONY:clean