add by zhj: Unix Domain Socket is the optimization of network socket, which is applicable to the situation that the server and the client are on the same machine. Compared with network socket, it can improve communication efficiency
Original text: https://www.jianshu.com/p/dc78b7ca006a
Author: Meopas 0 μ 0
Source: Jianshu
Recently, when building Nginx+Gunicorn, the two processes can communicate with each other through a file with a suffix of. sock. Most of the previously encountered processes communicate through pipes or TCP connections, so it took a little time to study.
There is a section of configuration in Nginx as follows:
upstream app_server { # fail_timeout=0 means we always retry an upstream even if it failed # to return a good HTTP response # for UNIX domain socket setups server unix:/tmp/gunicorn.sock fail_timeout=0; # for a TCP configuration # server 192.168.0.7:8000 fail_timeout=0; }
Unix Domain Socket is called Unix Domain Socket, or UDS for short. It is developed on the basis of Socket API API was originally suitable for the communication between processes on different machines, and of course, it can also be used for the communication between different processes on the same machine (through localhost). Later, on this basis, an IPC mechanism was developed for inter process communication. Compared with the original network Socket, UDS only needs to copy data between processes, without processing protocols, calculating checksums, maintaining serial numbers, adding and Delete network burst head and send confirmation message, so it is more efficient and faster. UDS provides flows and packets similar to TCP/UDP, but both are reliable and messages are not lost or out of order.
The creation of UDS is similar to that of network Socket:
- Create a Socket, specify the family as AF ﹣ UNIX, and type supports sock ﹣ straem and sock ﹣ Dgram;
- Different from network Socket, the object bound by UDS is a file;
- Start listening for accept;
- Receive the request accept, establish a new socket for each connection, and remove it from the listening queue queue.
Here is a demo code of echo server written by python:
import socket import os server_address = "/Users/Temp/socket.sock" if os.path.exists(server_address): raise Exception("The sock file is exist") server_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) server_socket.bind(server_address) server_socket.listen(1) try: while True: print("Start accept!") client_socket,client_address = server_socket.accept() while True: print("Connect from:", client_address) data = client_socket.recv(1024) if not data: print("Connection closed by client!\n") break else: print("Received:", data) print("Send back:", client_socket.sendall(data)) os.unlink(server_address) except Exception as e: print(e) if os.path.exists(server_address): os.unlink(server_address)
The UDS client is the same as the network Socket, except that the connect is a file. The following is the client demonstration code written by pyrhon:
import socket import os import time server_address = "/Users/Temp/socket.sock" if not os.path.exists(server_address): raise Exception("The sock file is not exist") print("Connect to socket:", server_address) client_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) try: client_socket.connect(server_address) except Exception as e: print(e) raise def send_test(client_socket, send_data): time.sleep(1) print("Send:", send_data) client_socket.send(send_data) time.sleep(1) recv_data = client_socket.recv(1024) print("Echo:", recv_data) print("Start communication!") send_data = b"Hello, world!" send_test(client_socket, send_data) send_data = b"My name is Tom!" send_test(client_socket, send_data) print("Close connection!") client_socket.close()
The operation results are as follows:
Connect to socket: /Users/Temp/socket.sock Start communication! Send: b'Hello, world!' Echo: b'Hello, world!' Send: b'My name is Tom!' Echo: b'My name is Tom!' Close connection!There is also a simple way to quickly create unnamed anonymous UDS (similar to pipes), using functions socket.socketpair([family[, type[, proto]]]), but this method is not universal, and can only be used between parent-child processes, not in unrelated processes.