Catalogue
- Directory
- Overview
- The socket function uses
- struct Sockaddr_un
- Socket
- Bind
- Listen
- Accept
- Connect
- Socket IPC Instance
- Server
- Client
- Run results
Overview
The socket API was originally designed for network communication, but later developed an IPC mechanism on the socket's framework, UNIX Domain socket.
Although the network socket can also be used for interprocess communication with the same host (via loopback address 127.0.0.1), Unix Domain sockets are more efficient for IPC:
- No need to go through the network protocol stack.
- No package unpacking required
- does not need to calculate the checksum
- No need to maintain serial numbers and answers, etc.
This is because the IPC mechanism is inherently reliable communication, and the network protocol is designed for unreliable communications. UNIX domain sockets also provide both stream-oriented and packet-oriented API interfaces, such as TCP and UDP, but stream-oriented UNIX domain sockets are also reliable, and messages are neither lost nor sequenced.
The process of using the UNIX Domain socket is very similar to the network socket, and the socket () is called to create a socket file descriptor, and address family is specified as Af_unix,type to select Sock_ The stream or Sock_dgram,protocol parameter is still specified as 0.
The most obvious difference between the UNIX domain socket and the network socket programming is that the address format is different, the structure of the Sockaddr_un, the network programming socket address is the IP address plus port number, and Unix Domain The address of the socket is the path of a socket-type file in the file system, which is created by the bind () call, and if the file already exists when bind () is called, the bind () error is returned.
The socket function uses
Next, explain the main functions that UNIX Domain socket programming uses.
struct Sockaddr_un
The address structure used by UNIX Domain sockets is defined as follows:
#define UNIX_PATH_MAX 108struct sockaddr_un { /* AF_UNIX */ char/* pathname */};
socket ()
#include <sys/types.h>#include <sys/socket.h>int socket(intintint protocol);
The parameters are defined as follows:
domain specifies the set of communication protocols for sockets (Af_unix and af_inet, etc.)
- Af_unix (same as af_local and Af_file) can only be used on a single UNIX system, using Af_unix to create a socket file on the system, and different processes to read and write this file to achieve communication.
- Af_inet is used for networking, so it is possible to allow communication between remote hosts.
Type specifies the types of sockets (Sock_stream and SOCK_DGRAM, etc.)
- Sock_stream indicates the use of the TCP protocol, which means that sequential, reliable, bidirectional, connection-oriented bit streams are provided.
- Sock_dgram indicates the use of the UDP protocol, which means that fixed-length, unreliable, non-connected communication is provided.
protocol specifies the transport protocol that is actually used. The most common are ipproto_tcp, ipproto_stcp, IPPROTO_UDP, IPPROTO_DCCP. If the entry is 0, the default protocol is selected based on the selected domain and type.
After the socket () function is called, the file descriptor is returned successfully, and 1 fails.
bind ()
#include <sys/types.h>#include <sys/socket.h>int bind(intconststruct sockaddr *addr, socklen_t addrlen);
Bind () assigns an address to the socket. When a socket is created by using the socket (), only the protocol that it uses is assigned, not the address. You must first call bind () to assign an address to the socket before accepting another host connection.
The parameters are defined as follows:
- SOCKFD: This is a descriptor for the socket.
- Addr: A pointer to the SOCKADDR structure (used to represent the assigned address).
- The length of the ADDRLEN:SOCKADDR structure.
Listen ()
#include <sys/types.h>#include <sys/socket.h>int listen(intint backlog);
When the socket and an address are bound, call the Listen () function to start listening for connection requests. However, this can only be used when there is a reliable data flow guarantee, such as sock_stream.
The parameters are defined as follows:
- The Sockfd:socket descriptor.
- Backlog: An integer that determines the size of the listening queue, which enters this listening queue when a connection request arrives. When the queue is full, a new connection request returns an error.
Returns 1 if the listener successfully returns 0.
Accept ()
#include <sys/types.h>#include <sys/socket.h>int accept(intstruct sockaddr *addr, socklen_t *addrlen);
When an application listens to a data flow-oriented connection from another host, it is notified through an event such as a UNIX select () system call. The connection must be initialized with the Accept () function. Accept () Creates a new socket for each connection and removes the connection from the listening queue.
The parameters are defined as follows:
- SOCKFD: The socket descriptor for the listener.
- Addr: Pointer to sockaddr struct, client address information.
- Addrlen: A pointer to the socklen_t that determines the size of the client structure body.
Accpet successfully returned a new socket descriptor with an error of 1. Further communication must pass through this socket.
Connect ()
#include <sys/types.h>#include <sys/socket.h>int connect(intconststruct sockaddr *addr, socklen_t addrlen);
The Connect () system call sets the connection for a socket, which has a file descriptor and a host address.
Socket IPC Instance
Next, simply implement a reference instance that communicates between processes through a UNIX Domain socket.
Server
#include <stdlib.h>#include <stdio.h>#include <string.h>#include <stddef.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <unistd.h>#define Qlen 8Char*socket_path="Wzy.socket";intMainintargcChar**ARGV) {intFD, CLIFD, N;structSockaddr_un un;Charbuf[ -];if(Argc >1) Socket_path = argv[1];if(FD = socket (Af_unix, Sock_stream,0)) <0) {perror ("Socket Error");Exit(1); }memset(&un,0,sizeof(un)); un.sun_family = Af_unix;strncpy(Un.sun_path, Socket_path,sizeof(Un.sun_path)-1); Unlink (Socket_path);if(Bind (FD, (structSOCKADDR *) &un,sizeof(un)) <0) {perror ("Bind error");Exit(1); }printf("UNIX Domain Socket bound\n");memset(&buf,0,sizeof(BUF));if(Listen (FD, Qlen) <0) {perror ("Listen error");Exit(1); } while(1) {if((Clifd = accept (FD, NULL, null)) = =-1) {perror ("Accpet Error");Continue; } while(n = Read (CLIFD, buf,sizeof(BUF))) >0) {printf("read%d bytes:%s\n", n, buf); }if(n = =-1) {Exit(-1); }Else if(n = =0) {printf("end\n"); Close (CLIFD); } }return 0;}
Client
#include <stdlib.h>#include <stdio.h>#include <string.h>#include <stddef.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <unistd.h>Char*socket_path="Wzy.socket";intMainintargcChar**ARGV) {intHdustructSockaddr_un un;Charbuf[ -];if(Argc >1) Socket_path = argv[1];if(FD = socket (Af_unix, Sock_stream,0)) <0) {perror ("Socket Error");Exit(1); }memset(&un,0,sizeof(un)); un.sun_family = Af_unix;strncpy(Un.sun_path, Socket_path,sizeof(Un.sun_path)-1);if(Connect (FD, (structSOCKADDR *) &un,sizeof(un)) <0) {perror ("Connect Error");Exit(-1); } while(scanf('%s ', buf)! = EOF) {if(Write (FD, buf,sizeof(BUF)) <0) {perror ("Write error");Exit(-1); } }return 0;}
Run Results
Server listens for data sent by the client:
The client uploads the following data:
UNIX Domain Socket IPC