socket IPC
socket API was originally designed for network communication, but later developed an IPC mechanism based on the socket framework, namely UNIX Domain Socket. Although the network socket can also be used for interprocess communication of the same host (through loopback address 127.0.0.1), but UNIX Domain Socket is more efficient for IPC: it does not need to go through the network protocol stack, pack and unpack, calculate checksum, maintain sequence number and response, but just copy application layer data from one process to another. This is because IPC mechanism is essentially reliable communication, while network protocol is unreliable communication Designed. UNIX domain sockets also provide stream oriented and packet oriented API interfaces, similar to TCP and UDP, but message oriented UNIX domain sockets are also reliable, and messages will not be lost or out of order.
UNIX Domain Socket is full duplex and has rich API interface semantics. It has obvious advantages over other IPC mechanisms. At present, it has become the most widely used IPC mechanism. For example, the communication between X Window server and GUI program is through UNIXDomain Socket.
the most obvious difference between UNIX Domain Socket and network socket programming is that the address format is different. The structure SOCKADDR is used_ UN means that the socket address of network programming is the IP address plus the end slogan, while the address of UNIX Domain Socket is the path of a socket type file in the file system. This socket file is created by calling bind(). If the file already exists when calling bind(), the bind() error is returned.
Compare network sockets
int socket(int domain, int type, int protocol);
Parameters:
domain: AF_UNIX, AF_LOCAL
type: SOCK_STREAM,SOCK_DGRAM
Socket address structure:
struct sockaddr_in { __kernel_sa_family_t **sin_family**; /* Address family */ Address structure type __be16 **sin_port**; /* Port number */ Port number struct in_addr **sin_addr**; /* Internet address */ IP address }; struct sockaddr_un { __kernel_sa_family_t **sun_family**; /* AF_UNIX */ Address structure type char **sun_path**[UNIX_PATH_MAX]; /* pathname */ socket file name(Including path) };
network sockets | local sockets | |
---|---|---|
Function parameters | domain: AF_INET type: SOCK_STREAM,SOCK_DGRAM | domain: AF_UNIX, AF_LOCAL type: SOCK_STREAM,SOCK_DGRAM |
Address structure | sockaddr_in | sockaddr_un |
Address structure initialization | struct sockaddr_in srv_addr srv_addr.sin_family=AF_INET srv_addr. sin port=htons(8888); srv_addr.sinaddr.s_addr=htonl(INADDR_ANY) bind(fd(structsockaddr*)&srv_addr,sizeof(srv_addr)) | struct sockaddr_un srv_addr srv_addr.sun_family=AF_UNIX/ AF_LOCAL strcpy(srv_addr. sun path,"srv. socket") len=brtsetof(struct sockaddr un, sium path+strlen("srv. socket") bind(fd,(struct sockaddr *)& srv_addr,1en) |
bind function | Call the bind function | If the bind function is called successfully, a socket will be created to ensure successful bind. Before that, use the unlink function |
client | Dependency "implicit binding" | The client cannot rely on "implicit binding" to create and initialize two address structures in the process of establishing communication. |
Local socket for communication
Communication flow
Server program
#include<iostream> #include<stdlib.h> #include<stdio.h> #include<unistd.h> #include<errno.h> #include<string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/un.h> #include <ctype.h> #include <arpa/inet.h> #include "wrap.h" using namespace std; //Define a port number #define SERVER_PORT 9527 //#define BUFSIZ _IO_BUFSIZ #define SERVER_ADDR "server.socket" int main (int argc,char *argv[]) { int link_fd=0;//The file descriptor used to establish the connection int cfd=0;//Used to communicate with the server int ret,len,size; char buf[BUFSIZ];//4096 //Create socket link_fd=Socket(AF_UNIX,SOCK_STREAM,0); //Check the return value to determine whether the creation is successful if(link_fd==-1) { sys_err("socket error"); } //Create initialization members of server and client structures struct sockaddr_un server_addr,client_addr;//Import header file #include < netinet / in h> //socklen_t client_addrlen; bzero(&server_addr,sizeof(server_addr)); server_addr.sun_family=AF_UNIX; strcpy(server_addr.sun_path,SERVER_ADDR); //Find the length of (local socket) binding address structure (2 bytes) and solve it by macro function len =offsetof(struct sockaddr_un,sun_path)+strlen(server_addr.sun_path); //Call the unlink function to ensure successful creation unlink(SERVER_ADDR); //Call the bind function to bind ret=bind(link_fd,(struct sockaddr*)&server_addr,len); //Determine whether the binding is successful if(ret==-1) { sys_err("bind error"); } //Set the maximum number of simultaneous connections to the server Listen(link_fd,128); cout<<("accept...")<<endl; while(1) { len =sizeof(client_addr); cfd=accept(link_fd,(struct sockaddr*)&client_addr,(socklen_t*)&len); //Print the file name of the communication len-=offsetof(struct sockaddr_un,sun_path); //To obtain the length of the file name, [subtract the first two bytes of the address structure] client_addr.sun_path[len]='\0'; cout<<"client bind filename "<<client_addr.sun_path<<endl; while((size=read(cfd,buf,sizeof(buf)))>0) { for(int i=0;i<size;i++) { buf[i]=toupper(buf[i]); } write(cfd,buf,size); } close(cfd); } close(link_fd); return 0; }
Client program
#include<iostream> #include <stdio.h> #include <unistd.h> #include <sys/socket.h> #include <string.h> #include <ctype.h> #include <arpa/inet.h> #include <sys/un.h> #include <stddef.h> #include "wrap.h" using namespace std; //Define a port number (server) #define SERVER_PORT 9527 #define SERVER_ADDR "server.socket" #define CLIENT_ADDR "client.socket" int main (int argc,char *argv[]) { int cfd, len; struct sockaddr_un servaddr, cliaddr; char buf[4096]; cfd = Socket(AF_UNIX, SOCK_STREAM, 0); bzero(&cliaddr, sizeof(cliaddr)); //Client address structure member initialization, used to create socket file and bind cliaddr.sun_family = AF_UNIX; strcpy(cliaddr.sun_path,CLIENT_ADDR); //Find the header length bytes plus the file length len = offsetof(struct sockaddr_un, sun_path) + strlen(cliaddr.sun_path); /* Calculate the effective length of the client address structure */ unlink(CLIENT_ADDR); bind(cfd, (struct sockaddr *)&cliaddr, len); /* The client also needs bind and cannot rely on automatic binding*/ bzero(&servaddr, sizeof(servaddr)); //Server address structure member initialization is used to connect / * construct server address*/ servaddr.sun_family = AF_UNIX; strcpy(servaddr.sun_path,SERVER_ADDR); len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path); /* Calculate the effective length of server-side address structure */ connect(cfd, (struct sockaddr *)&servaddr, len); while (fgets(buf, sizeof(buf), stdin) != NULL) { write(cfd, buf, strlen(buf)); len = read(cfd, buf, sizeof(buf)); write(STDOUT_FILENO, buf, len); } close(cfd); return 0; }
Operation results
Server:
client: