UNIX domain protocol (local communication protocol)

Overview

The Unix domain protocols are not an actual protocol suite, but a way of performing client/service communication on a single host. It is a method of inter-process communication (IPC).

It provides two types of sockets: byte stream socket SOCK_STREAM (somewhat like TCP) and datagram socket SOCK_DGRAM (somewhat like UDP)

The UNIX domain datagram service is reliable, with no message loss or delivery errors.

The IP protocol identifies client servers through IP addresses and port numbers. The protocol addresses used to identify clients and servers in the UNIX domain protocol are path names in ordinary file systems.

Features of UNIX domain protocols:

1. Compared with UNIX domain socket domain TCP socket, the transmission speed of the former is twice that of the latter on the same host
. UNIX domain sockets only copy data, do not perform protocol processing, do not add or remove network headers, do not calculate checksums, and produce no

The sequence number is generated, and there is no need to send a confirmation message.

2. UNIX domain sockets can pass file descriptors between processes on the same host

3. The difference between UNIX domain socket domain and traditional socket domain is that the path name is used to represent the description of the protocol family.

UNIX domain protocol address

#define UNIX_PATH_MAX 108
struct sockaddr_un
{
    __kernel_sa_family_t sun_family; /* Communication protocol AF_UNIX / AF_LOCAL */
    char sun_path[UNIX_PATH_MAX]; /* pathname */
    //The address of the UNIX domain protocol is the absolute path name in the local file system ending with '\0'
    //It will be created automatically and does not need to be created in advance.
};

The programming process of UNIX domain protocol for local inter-process communication is the same as TCP/UDP, except that the specific protocol address is used

Use file path name

Server: First create a socket -> bind address -> listen -> accept client connection -> start communication after successful connection -> close socket

Client: First create a socket -> bind address -> connect to the server -> start communication -> close the socket.

UNIX domain protocol inter-process communication method 1: socketpair function

[Header file]

#include <sys/types.h>
#include <sys/socket.h>

[Function prototype]

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

[Function]

This function is only used for Unix domain sockets. Its domain must be AF_LOCAL, the protocol parameter must be 0, and the type can be SOCK_STREAM or SOCK_DGRAM. It is similar to the ordinary pipe created by calling pipe. The difference is that ordinary pipes can only perform single operations. One-way reading or one-way writing, while the pipe is full-duplex and can read and write in one direction.

[Parameter meaning]

[domain]: represents the protocol family, which can only be
AF_LOCAL
or
AF_UNIX
. (SOCK_NONBLOCK and SOCK_CLOEXEC are also supported since Linux 2.6.27)

[type]: Indicates the protocol, which can be SOCK_STREAM or SOCK_DGRAM. SOCK_STREAM is based on TCP, while SOCK_DGRAM is based on UDP

[protocol]: Indicates the type, which can only be 0

[sv]: Socket handle pair. The two handles have the same function and can perform two-way read and write operations.

[Return value]

0 means the creation is successful, -1 means the creation fails, and errno indicates a specific error number. The specific error number is as follows:

EAFNOSUPPORT:The specified address is not supported on this machine.
EFAULT:
Address sv cannot point to a valid process address space.

EMFILE: The system limit for file descriptors has been reached, or the process has used an excessive number of descriptors.

EOPNOTSUPP:The specified protocol does not support creating a socket pair.

EPROTONOSUPPORT:The specified protocol is not supported by this machine.

[Remarks]

1. This function can only be used for
UNIX
area(
LINUX
)Down.

2. It can only be used for communication between related processes (or threads).

3. The created socket pairs have the same function and can be read and written (while pipes
PIPE
Only one-way reading and writing can be performed).

4. When reading, there must be content in the pipe, otherwise it will be blocked; in short, this function is blocked.

[Sample code]

/*socketpair1.c*/
#include <sys/types.h>
#include <sys/socket.h>
#include 
#include 
int main()
{
    int sv[2];
    int result = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
    if (result < 0){
        exit(1);
    }
    printf("sv[0] is : %d \\
", sv[0]); //These two socket handles are not the same, but their functions are the same
    printf("sv[1] is : %d \\
", sv[1]);
    if (fork())
    {
        /* Parent process */
        int val = 0;
        pid_t pid = getpid();
        close(sv[1]); //The parent process closes the read and write permissions of sv[1]
        while (1)
        {
             + + val;
            printf("%d send message: %d\\
", pid, val);
            write(sv[0], & amp;val, sizeof(val)); //The parent process writes data to the pipe
            //You can also read it
            // read(sv[0], & amp;val, sizeof(val)); //If the word process does not write data, it will cause congestion here
            //printf("%d receive message: %d\\
", pid, val);
            sleep(1);
        }
    }
    else
    {
        /*child process*/
        int val = 0;
        close(sv[0]); //The word process closes the read and write permissions of sv[0]
        pid_t pid = getpid();
        while(1)
        {
            read(sv[1], & amp;val, sizeof(val)); //Word process gets data from the pipe
            printf("%d receive message: %d\\
", pid, val);
            // printf("%d receive message: %d\\
", pid, val);
            //You can also write
            // write(sv[1], & amp;val, sizeof(val));
        }
    }
}

Inter-process communication method 2 of UNIX domain protocol: socket communication method

The way the UNIX domain protocol performs local communication is very similar to TCP and UDP. Let’s write an example of communication between the client and the server using the streaming socket of the UNIX domain protocol. Using the streaming socket, the local communication The communication method must be similar to TCP. This communication method also has the characteristics of TCP communication.

Client sample program:

#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include<netinet/in.h> //In order to use the IPV4 address structure
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>

#define UNIX_PATH_PS "/home/china/sockp1" //Connected socket address
#define UNIX_PATH_PC "/home/china/sockp2" //Binded socket address

int main(int argc,char *argv[])
{
    system("rm /home/china/sockp2"); //Prevent file renames

    //1.Create a socket
    int sockfd = socket(AF_UNIX, SOCK_STREAM,0); //Create a local communication UNIX stream socket
    if(-1 == sockfd)
    {
        perror("create socket failed");
        exit(-1);
    }

    //2. Bind a communication address (so that the server can see me), but do not bind it
    struct sockaddr_un local;
    memset( & amp;local,0,sizeof(struct sockaddr_un)); //Clear the structure
    local.sun_family = AF_UNIX;
    strcpy(local.sun_path,UNIX_PATH_PC);
    int ret = bind(sockfd,(struct sockaddr*) & amp;local,sizeof(local));
    if(ret == -1)
    {
        perror("bind error");
        exit(-1);
    }
    printf("bind success\\
");
    //Connect to target server
    struct sockaddr_un saddr; //Save the address of the target server (local file name)
    memset( & amp;saddr,0,sizeof(struct sockaddr_un)); //Clear the structure
    saddr.sun_family = AF_UNIX;
    strcpy(saddr.sun_path,UNIX_PATH_PS);
    ret = connect(sockfd, (struct sockaddr*) & amp;saddr,sizeof(saddr)); //Request to connect to the target server
    if(ret == -1)
    {
        perror("connect error");
        exit(-1);
    }
    printf("connect success\\
");
    char buf[1024] = {0};
    //Read information
    ret = recv(sockfd,buf,1024, 0);
    if(ret == -1)
    {
        perror("recv error");
    }
    printf("recv size:%d,recv data:%s\\
",ret,buf);
    //send Message
    ret = sendto(sockfd,"byebye",6,0,NULL,0);
    if(ret == -1)
    {
        perror("sendto error");
    }
    printf("sendto size:%d\\
",ret);
    //Close the socket
    shutdown(sockfd,SHUT_RDWR);
    close(sockfd);
    return 0;
}

Server program example:

#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include<netinet/in.h> //In order to use the IPV4 address structure
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#define UNIX_PATH_PS "/home/china/sockp1"

int main(int argc,char *argv[])
{
    system("rm /home/china/sockp1"); // Ensure that the file is not used

    //1.Create a socket
    int sockfd = socket(AF_UNIX, SOCK_STREAM,0); //Create a local communication UNIX stream socket
    if(-1 == sockfd)
    {
        perror("create socket failed");
        exit(-1);
    }

    //2. Bind a communication address (as the address of the server itself)
    struct sockaddr_un local; //Save the server's address (file name)
    memset( & amp;local,0,sizeof(struct sockaddr_un)); //Clear the structure
    local.sun_family = AF_UNIX;
    strcpy(local.sun_path,UNIX_PATH_PS);
    int ret = bind(sockfd,(struct sockaddr*) & amp;local,sizeof(local)); //Bind server address
    if(ret == -1)
    {
        perror("bind error");
        exit(-1);
    }
    printf("bind success\\
");

    //3. Start monitoring a socket
    listen(sockfd,250);

    //4. Wait for client connection
    while(1)
    {
        struct sockaddr_un caddr; //Save the client's address (file name)
        socklen_t len = sizeof(caddr);
        int confd = accept(sockfd,(struct sockaddr*) & amp;caddr, & amp;len); //Blocking and waiting for client connection
        if(confd > 0) //The client connects successfully and returns a connection socket specifically used to communicate with the client.
        {
            //A client connection is successful. Open a process/thread to handle the connection.
            printf("client path:%s\\
",caddr.sun_path);
            ret = sendto(confd,"nishiliangzaima?",20,0,NULL,0); //Send message
            if(ret == -1)
            {
                perror("sendto error");
            }
            char buf[1024] = {0};
            ret = read(confd,buf,1024); //Receive message
            if(ret <= 0)
            {
                perror("recv error");
            }
            printf("recv size:%d,recv data:%s\\
",ret,buf);
            close(confd);//Close the connection socket
        }
    }
    //Close the socket
    shutdown(sockfd,SHUT_RDWR);
    close(sockfd);
    return 0;
}