Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use linux socket

2025-04-03 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)05/31 Report--

This article introduces the relevant knowledge of "how to use linux socket". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Socket, also known as socket, is a way of Linux cross-process communication (IPC). It can achieve not only cross-process communication within the same host, but also cross-process communication between different hosts.

The operating environment of this tutorial: linux5.9.8 system, Dell G3 computer.

The original meaning of socket is "socket". In the field of computer communication, socket is translated as "socket", which is a convention or a way of communication between computers. Through the convention of socket, one computer can receive data from other computers and send data to other computers.

Socket in linux

Socket is a way of Linux inter-process communication (IPC,Inter Process Communication, for more information: summary of Linux inter-process communication). Compared with other IPC methods, Socket is better in that it can not only achieve cross-process communication within the same host, it can also achieve cross-process communication between different hosts. According to the difference of communication domain, it can be divided into two types: Unix domain socket and Internet domain socket.

1. Internet domain socket

Internet domain socket is used to implement inter-process communication on different hosts. In most cases, what we call socket refers to internet domain socket. (socket refers to internet domain socket unless it is specifically referred to below. )

To achieve cross-process communication between different hosts, the first problem to be solved is how to uniquely identify a process. We know that each process on the host has a unique pid, and the identification of cross-process communication processes on the same host can be solved through pid. But if the two processes are not on the same host, it is possible for pid to repeat, so it is not applicable in this scenario, is there any other way? We know that the host can be locked only through the host IP, and the program can be located through the port, and we also need to know what protocol to use for interprocess communication. In this way, the combination of "IP+ Port + Protocol" can uniquely identify a process on a host in the network. This is also the main parameter for generating socket.

After each process has a unique identity, the next step is communication. Communication can not be clapped by a slap, where there is a sender program, there is a receiver program, and Socket can be regarded as an endpoint in the communication connection between the two ends. The sender writes a piece of information into the sender Socket, the sender Socket sends this message to the receiver Socket, and finally the message is transmitted to the receiver. As for how the information from the sender Socket to the receiver Socket is the operating system and network stack should worry about, we do not need to know the details. As shown in the following figure:

In order to maintain the connection between the two ends, it is not enough for our socket light to have its own unique identity, but also needs each other's unique identity, so a sender and receiver Socket mentioned above are actually only half, and a complete Socket should be a 5-dimensional array composed of [protocol, local address, local port, remote address, remote port]. For example, the Socket of the sender is [tcp, sender IP, sender port, receiver IP, receiver port], then the receiver Socket is [tcp, receiver IP, receiver port, sender IP, sender port].

For example, to deepen our understanding, for example, when I send you Wechat to contact you, we are the process, Wechat client is Socket, and WeChat account is our only logo. As for the details of how Tencent sent Wechat messages to your Wechat, we don't need to care about them. In order to maintain our contact, it is not enough to have Wechat client in our socket. We also have to add friends so that we can find each other through the friend list. You in my Wechat client's friend list is my complete Socket, while I in your Wechat client's friend list is your complete Socket. I hope I didn't knock you out.

Socket can also be divided into three types according to different communication protocols: streaming socket (SOCK_STREAM), Datagram socket (SOCK_DGRAM) and original socket.

Streaming socket (SOCK_STREAM): the most common socket that uses the TCP protocol to provide reliable, connection-oriented traffic. Ensure that the data transmission is correct and sequential. Applied to Telnet remote connections, WWW services, etc.

Datagram socket (SOCK_DGRAM): using the UDP protocol to provide connectionless services, data is transmitted through independent messages, is unordered, and does not guarantee reliability. Applications that use UDP should have their own protocols for validating data.

Original socket: allows direct access to low-level protocols such as IP or ICMP, mainly for testing new network protocol implementations, etc. The original socket is mainly used for the development of some protocols and can be used for relatively low-level operations. It is powerful, but it is not as easy to use as the two sockets described above, and the general program does not involve the original socket.

The working process of the socket is shown in the following figure (take streaming socket as an example, the flow of the Datagram socket is different. For more information, please see: what is a Socket?): the server starts first, establishes a socket by calling socket (), then calls bind () to associate the socket with the local network address, and then calls listen () to prepare the socket for listening, and specifies the length of its request queue. Accept () is then called to receive the connection. After establishing the socket, the client can call connect () to establish a connection with the server. Once the connection is established, the client and server can send and receive data by calling read () and write (). Finally, after the data transfer is finished, both parties call close () to close the socket.

From the perspective of TCP connection, the above process can be summarized as shown in the figure. You can see that the three-way handshake of TCP represents the process of establishing a Socket connection. After establishing the connection, you can transfer data to each other through read,wirte, and then wave the last four times to disconnect and delete Socket.

2. Unix domain socket

Unix domain socket, also known as IPC (inter-process communication Inter-process Communication) socket, is used to achieve inter-process communication on the same host. Socket was originally designed for network communication, but then an IPC mechanism, UNIX domain socket, was developed on the framework of socket. Although network socket can also be used for inter-process communication of the same host (via loopback address 127.0.0.1), UNIX domain socket is more efficient for IPC: no need to go through the network protocol stack, no need to package and unpack, calculate checksum, maintain sequence number and reply, etc., but just copy application layer data from one process to another. This is because the IPC mechanism is essentially reliable communication, while network protocols are designed for unreliable communication.

UNIX domain socket is full-duplex, API interface is rich in semantics, compared with other IPC mechanisms have obvious advantages, has become the most widely used IPC mechanism, such as X Window server and GUI programs are communicated through UNIX domain socket. Unix domain socket is a component of the POSIX standard, so don't be confused by the name, the linux system also supports it.

Students who know Docker should know that Docker daemon listens for a docker.sock file, the default path for this docker.sock file is / var/run/docker.sock, and this Socket is a Unix domain socket. It will be described in detail in the later practice.

Socket practice

The best way to learn programming well is to practice. Next, let's actually use Socket communication and look at the Socket file

1. Internet domain socket practice

Now we will use socket to write a server, because I have less experience in C language, so here I choose to use GoLang practice. The function of server is very simple: listen on port 1208, return pong when you receive ping, return xxx when you receive echo xxx, and close the connection when you receive quit. Socket-server.go code reference article: Socket programming with Go | starts with Luo Dust. As follows:

Package mainimport ("fmt"net"strings") func connHandler (c net.Conn) {if c = = nil {return} buf: = make ([] byte, 4096) for {cnt Err: = c.Read (buf) if err! = nil | | cnt = = 0 {c.Close () break} inStr: = strings.TrimSpace (string (buf [0: cnt])) inputs: = strings.Split (inStr) "") switch inputs [0] {case "ping": c.Write ([] byte ("pong\ n")) case "echo": echoStr: = strings.Join (inputs [1:]) "") + "\ n" c.Write ([] byte (echoStr)) case "quit": c.Close () break default: fmt.Printf ("Unsupported command:% s\ n" Inputs [0])}} fmt.Printf ("Connection from% v closed. \ n ", c.RemoteAddr ()} func main () {server, err: = net.Listen (" tcp ",": 1208 ") if err! = nil {fmt.Printf (" Fail to start server,% s\ n ", err)} fmt.Println (" Server Started... ") For {conn, err: = server.Accept () if err! = nil {fmt.Printf ("Fail to connect,% s\ n", err) break} go connHandler (conn)}}

In the Unix-like system where everything is a file, the socket produced by the process is represented by the socket file, and the process transmits the message by reading and writing to the socket file. On Linux systems, the socket file is usually under the / proc/pid/fd/ file path. Launch our socket-server and let's take a peek at the corresponding socket file. Start server first:

# go run socket-server.go Server Started...

To open another window, let's first look at the pid of the server process, using the lsof or netstat command:

# lsof-I: 1208COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEsocket-se 20007 root 3u IPv6 470314 0t0 TCP *: 1208 (LISTEN) # netstat-tupan | grep 1208tcp6 00: 1208:: * LISTEN 20007/socket-server

You can see that our server pid is 20007. Next, let's take a look at the socket that server listens to:

# ls-l / proc/20007/fdtotal 0lrwx-1 root root 64 Sep 11 07:15 0-> / dev/pts/0lrwx- 1 root root 64 Sep 11 07:15 1-> / dev/pts/0lrwx- 1 root root 64 Sep 11 07:15 2-> / dev/pts/0lrwx- 1 root root 64 Sep 11 07:15 3-> 'socket: [470314]' lrwx- 1 root root 64 Sep 11 07:15 4-> 'anon_inode: [eventpoll]'

You can see that / proc/20007/fd/3 is a link file pointing to socket: [470314], which is the socket on the server side. Socket-server startup goes through three processes: socket ()-- > bind ()-- > listen (). This LISTEN socket is created to listen for connection requests to port 1208.

We know that socket communication requires a pair of socket: server and client. Now let's open another window and start a client with telnet on the same machine in socket-server to see the socket on the client side:

# telnet localhost 1208Trying 127.0.0.1...Connected to localhost.Escape character is'^]'.

Continue to view the file descriptor opened on the server port

# lsof-I: 1208COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEsocket-se 20007 root 3U IPv6 470314 0t0 TCP *: 1208 (LISTEN) socket-se 20007 root 5U IPv6 473748 0t0 TCP localhost:1208- > localhost:51090 (ESTABLISHED) telnet 20375 ubuntu 3u IPv4 473747 0t0 TCP localhost:51090- > localhost:1208 (ESTABLISHED)

We find that there are two more than the previous results, these three are:

*: 1208 (LISTEN) is the file name of server to listener socket, and the process pid is 20007

Localhost:1208- > localhost:51090 (ESTABLISHED) is a new socket established by server for client, which is responsible for communicating with client. The process pid is 20007.

Localhost:51090- > localhost:1208 (ESTABLISHED) is a new socket established by client for server, which is responsible for communicating with server. The process pid is 20375.

The new socket created by server and client can be seen under the / proc/pid/fd/ file path, so I won't repeat it here. From the result of Article 3, we can see that the first two socket,LISTEN socket and the newly created ESTABLISHED socket belong to the server process. For each linked server process, a new socket is created to link the client. The source IP and the source port of this socket are the IP and port of server, and the destination IP and destination port are the IP and port of client. The corresponding client also creates a new socket whose source IP and source port and destination IP and destination port are exactly the opposite of the socket created by server, and the port of client is a high port randomly assigned by a host.

From the above results, we can answer the question "will a new port be generated after the server socket.accept?" The answer is no. The listening port of server will not change, nor will the port of the new socket created by server for client, which in this case is 1208. Is it so difficult that there will be no port conflicts? Of course not, we know that socket is uniquely determined by a 5-dimensional array [protocol, local IP, local port, remote IP, remote port]. Socket: *: 1208 (LISTEN) and socket: localhost:1208- > localhost:51090 (ESTABLISHED) are different socket. So what's the use of this LISTEN socket? My understanding is that when a packet requesting a connection is received, such as a SYN request from TCP, the connection will be received by LISTEN socket and processed by accept. If it is a client packet after a connection has been established, the data is put into the receive buffer. In this way, when the server needs to read the data of the specified client, it can use the ESTABLISHED socket to fetch the specified data in the buffer through the recv or read function, which ensures that the response will be sent to the correct client.

It was mentioned above that the client host assigns a random port to the process initiating the connection to create a socket, while the server process creates a new socket for each connection. Therefore, for the client, since there are only a maximum of 65535 ports, of which 1024 are not allowed for user programs, there can only be a maximum of 64512 concurrent connections. For the server, the total number of concurrent connections is limited by the number of file handles that a process can open, because socket is also a kind of file, each socket has a file descriptor (FD,file descriptor), and each socket created by the process opens a file handle. This upper limit can be viewed through ulimt-n, and the concurrent connection limit of server can be increased by adding ulimit. The ulimit of the server machine in this example is:

# ulimit-n1024

After talking about the socket creation between the server and the client for a long time, let's take a look at the socket communication between the server and the client. Remember that our server can respond to three commands, ping,echo and quit, let's try:

# telnet localhost 1208Trying 127.0.0.1...Connected to localhost.Escape character is'^]'. Pingpongecho Hello,socketHello,socketquitConnection closed by foreign host.

We can see the communication between client and server through socket.

At this point, let's summarize the whole process of initiating a connection from telnet, issuing ping from the client, responding to pong from the server, and finally disconnecting the connection from the client quit:

Telnet initiates a connection request to localhost:1208

Server receives the request packet through socket: TCP *: 1208 (LISTEN) for accept processing

Server returns socket information to the client, which receives the server socket message, assigns a random port 51090 to the client process, and then creates socket: TCP localhost:51090- > localhost:1208 to connect to the server.

The server process creates a new socket: TCP localhost:1208- > localhost:51090 to connect to the client

Client sends ping,ping packet send to socket: TCP localhost:51090- > localhost:1208

The server receives the ping packet through socket: TCP localhost:1208- > localhost:51090, and returns the pong,pong packet back to the client through the original route to complete a communication.

The client process initiates a quit request. After reaching the server through the same socket path mentioned above, the server cuts off the connection, and the server deletes the socket: TCP localhost:1208- > localhost:51090 release file handle; the client deletes socket: TCP localhost:51090- > localhost:1208 and releases port 51090.

In the above process, socket to socket also go through the operating system, network stack and other processes, which will not be described in detail here.

2. Unix domain socket practice

We know that docker uses the client-server architecture, and the user enters commands through docker client, and client relays the commands to docker daemon for execution. Docker daemon listens on a unix domain socket to communicate with other processes, and the default path is / var/run/docker.sock. Let's take a look at this file:

# ls-l / var/run/docker.sock srw-rw---- 1 root docker 0 Aug 31 01:19 / var/run/docker.sock

You can see that its Linux file type is "s", which is socket. With this socket, we can directly call the API of docker daemon to operate, and then we call API through docker.sock to run a nginx container, which is equivalent to executing on docker client:

# docker run nginx

Unlike the last command on docker client, running the container through API requires two steps: creating the container and starting the container.

1. To create the nginx container, we use the curl command to call docker API and specify the Unix domain socket through-- unix-socket / var/run/docker.sock. First, call / containers/create, and pass the parameter to specify the image as nginx, as follows:

# curl-XPOST-- unix-socket / var/run/docker.sock-d'{"Image": "nginx"}'- H 'Content-Type: application/json' http://localhost/containers/create{"Id":"67bfc390d58f7ba9ac808d3fc948a5d4e29395e94288a7588ec3523af6806e1a","Warnings":[]}

two。 Start the container. By creating the container id returned by the container in the previous step, let's start the nginx:

# curl-XPOST-unix-socket / var/run/docker.sock http://localhost/containers/67bfc390d58f7ba9ac808d3fc948a5d4e29395e94288a7588ec3523af6806e1a/start

# docker container lsCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES67bfc390d58f nginx "/ docker-entrypoint." About a minute ago Up 7 seconds 80/tcp romantic_heisenberg

So far, through Unix domain socket, we have realized the communication between the client process curl and the server process docker daemon, and successfully called docker API to run a nginx container.

It is worth noting that when connecting to the server's Unix domain socket, we directly specify the server's socket file. When using Internet domain socket, we specify the IP address and port number of the server.

That's all for the content of "how to use linux socket". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report