[Python] Network programming - Socket (1)

1. Socket overview

Socket, the original meaning is "socket", in the field of computer communication, Socket is generally translated as "socket". Baidu Encyclopedia's definition of Socket is as follows: "The so-called socket (Socket) is the abstraction of the endpoints for two-way communication between application processes on different hosts in the network. A socket is one end of process communication on the network, providing It defines the mechanism for the application layer process to exchange data using the network protocol. From the perspective of its position, the socket is connected to the application process and connected to the network protocol stack. It is the interface for the application program to communicate through the network protocol. The interface for interacting with the stack" [1] .

How to understand? In order to understand the definition of Socket in the above paragraph, we need to briefly understand the TCP/IP protocol. TCP/IP protocol, that is, Transmission Control Protocol/Internet Protocol (Transmission Control Protocol/Internet Protocol), refers to a protocol cluster that can realize information transmission between multiple different networks, and it is a general term for a series of network communication protocols [2 ] . In layman's terms, the TCP/IP protocol is a description of the rules that must be followed for communication between computers. Only by following these rules can computers communicate with each other [3] . The TCP/IP protocol adopts a 4-layer structure, which are application layer, transport layer, network layer and link layer, as shown in Figure 1 below [1] [4] :

insert image description here

Figure 1. TCP/IP protocol structure
 
  • Application Layer: The application layer is responsible for handling specific application details. The protocols of the application layer mainly include Telnet, FTP, SMTP and so on.
  • Transport layer: The transport layer, also known as the transport layer, is mainly responsible for providing communication between applications. The protocols of the transport layer mainly include TCP and User Datagram Protocol (User Datagram Protocol, UDP).
  • Network layer: The network layer is also known as the Internet layer and is mainly responsible for the communication between neighboring computers. The protocols of the network layer mainly include IP, ICMP, and IGMP.
  • Link layer: The link layer is also called the data link layer or the network interface layer, which usually includes the device driver in the operating system and the corresponding network interface card in the computer. The link layer is mainly responsible for sending and receiving IP datagrams for the IP module, sending ARP requests and receiving ARP responses for the ARP module, and sending RARP requests and receiving RARP responses for RARP. The protocols of the link layer mainly include ARP and RARP.

Socket is the software abstraction layer between the application layer and the transport layer, as shown in Figure 2 below. Socket is the encapsulation of TCP/IP protocol [5] . Socket provides a set of interfaces for applications to interact with the network protocol stack. Through Socket, applications can easily interact with the network protocol stack, so that different applications can communicate.

insert image description here

Figure 2. The position of Socket in the TCP/IP protocol
 

Therefore, we can abstract Socket as an endpoint for communication between applications, as shown in Figure 3 below.

insert image description here

Figure 3. Socket is an abstraction of an endpoint for two-way communication between application processes on different hosts in the network
 

To understand more generally, just as we can get power supply from the grid by plugging the plug into the socket, the application needs to be connected to the Internet before receiving or sending data, and Socket is a tool used to connect the application to the Internet [6] .

insert image description here
Typical applications of Socket are web servers and browsers: the browser obtains the URL input by the user and initiates a request to the server; the server analyzes the received URL and returns the corresponding webpage content to the browser; Present elements such as text, pictures, and videos to users [6] .


2. Socket creation

In Python, we use the socket() function to create a socket, and its syntax is as follows (you need to import the socket module first) [7] :

socket.socket([family[, type[, proto]]])  # 使用给定的地址族、套接字类型及协议号来创建套接字

Parameter description [7] - [9] :

  • family: address family, this parameter defaults to socket.AF_INET.

insert image description here

  • type: socket type, the parameter defaults to socket.SOCK_STREAM.

insert image description here

  • protocol: protocol number, generally defaulted to 0, so that the system will automatically select the appropriate protocol according to the address family and socket type.

3. Socket object built-in method

In this part, we only introduce a few important methods that we will use below. For other methods, please refer to the document [10] .

method describe
server method
socket.bind(address) Bind the socket to the address address , the format of the address depends on the above address family. For AF_INET, the address is expressed in the form of a tuple (host, port).
socket.listen([backlog]) Allows the server to accept connections, i.e. listen for connections. backlog specifies the maximum number of connections that the system can suspend before rejecting the connection. The value should be at least 0, and most applications should set it to 5.
socket.accept() Accept the connection. Socket must first be bound to an address and listen for connections. This method returns a pair (conn, address), where conn is a new Socket object for sending and receiving data on the connection; address is the address bound to the Socket at the other end of the connection.
client method
socket.connect(address) Connect to the socket at address . The format of the address depends on the address family mentioned above.
socket.connect_ex(address) An extended version of the connect method. The difference is that this method will return an error indicator when an error occurs, instead of throwing an exception when an error occurs like connect. If the method succeeds, the error indicator is 0; otherwise, the error indicator is the value of the variable errno . This method is useful to support, for example, asynchronous connections.
public method
socket.recv(bufsize[, flags]) Receive data, the return value is a byte object, representing the received data. bufsize specifies the maximum amount of data that can be received at one time.
socket.send(bytes[, flags]) To send data, the Socket must be connected to a remote Socket. This method returns the number of bytes sent, which may be less than the number of bytes in bytes .
socket.sendall(bytes[, flags]) To send data, the Socket must be connected to a remote Socket, and return None if successful. Unlike the send method, this method will keep sending data from bytes until all data has been sent, or an error occurs.
socket.recvfrom(bufsize[, flags]) Receive data, the return value is a pair (bytes, address), where bytes is a byte object representing the received data, and address is the address of the Socket that sent the data.
socket.sendto(bytes, flags, address) Send data, the Socket cannot be connected to a remote Socket, because address specifies the target Socket. This method returns the number of bytes sent.
socket.close() Close the socket.

4. General idea of ​​Socket programming

4.1 The general idea of ​​Socket programming based on TCP

server [11] :

  • Create server Socket: socket.socket(type=socket.SOCK_STREAM)
  • Bind the created server Socket to an ip and port: socket.bind()
  • Listen to the client's connection request: socket.listen()
  • Accept the connection request from the client: socket.accept()
  • Receive data from the client, or send data to the client: socket.recv(), or socket.send()/socket.sendall()
  • Close the connection: socket.close()

Client [11] :

  • Create client Socket: socket.socket(type=socket.SOCK_STREAM)
  • Connect the client Socket to the server ip and port: socket.connect(), socket.connect_ex()
  • Receive data from the server, or send data to the server: socket.recv(), or socket.send()/socket.sendall()
  • Close the connection: socket.close()

The above process can be summarized as shown in Figure 4 below:
insert image description here

Figure 4. Flow chart of TCP-based Socket programming [11]
 

Let's take daily phone calls as an example, and first understand the general idea of ​​the above-mentioned TCP-based Socket programming visually and intuitively [6] . If you are interested, you can learn more about the TCP protocol.

Server - equivalent to the receiving party :

  • Create a server socket: It is equivalent to buying a phone/mobile phone according to the network standard, landline, 5G mobile phone or satellite phone?
  • Bind the created server Socket to an ip and port: it is equivalent to applying for a number for a phone/mobile phone, through which the designated person can be contacted.
  • Listen to the connection request of the client: it is equivalent to connecting the phone/mobile phone to the network and waiting for someone to call.
  • Accept the client's connection request: it is equivalent to answering the phone, so that a call connection is established.
  • Receive data from the client, or send data to the client: it is equivalent to talking on the phone and can talk in two directions.
  • Close Connection: Equivalent to hanging up the phone or turning off the phone/handset.

Client - equivalent to the caller :

  • Create a client socket: it is equivalent to buying a phone/mobile phone according to the network standard, landline, 5G mobile phone or satellite phone?
  • Connect the client Socket to the server ip and port: it is equivalent to making a call, and you have to enter the other party's number.
  • Receive data from the server, or send data to the server: it is equivalent to talking on the phone, and can talk in two directions.
  • Close Connection: Equivalent to hanging up the phone or turning off the phone/handset.

Just like our daily calls, both parties need to establish a connection before they can speak. The server needs to use the socket.listen() and socket.accept() methods, and the client needs to use the socket.connect()/socket.connect_ex() method first Establish a connection with each other before network communication can take place.


Notes :

  1. The host in the network can be uniquely identified by "ip address", and the application program on the host can be uniquely identified by "protocol + port" [12] . Bind the Socket to an ip and port, so that the corresponding application can communicate over the network through the Socket.
  2. The backlog parameter in the socket.listen([backlog]) method specifies the maximum number of connections that the system can suspend before rejecting the connection. This is similar to our daily phone calls. If we receive other calls at the same time or during the call, these calls can be hung up and wait until they are answered.

Next, let's take the following code as an example to further understand the general idea of ​​the above-mentioned TCP-based Socket programming.

#!/usr/bin/env python
# -*- coding:utf-8 -*-

""" 服务器 """

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建服务器Socket
s.bind(('127.0.0.1', 8888))  # 绑定创建的服务器Socket到一个ip和端口
s.listen(5)  # 监听客户端的连接请求
print("Waiting connection from client...")
conn, address = s.accept()  # 接受客户端的连接请求
print("Connected by {}".format(address))  # 打印客户端Socket的地址
receive_message = conn.recv(1024).decode()  # 接收客户端传来的数据并解码
print("Message received: {}".format(receive_message))  # 打印客户端传来的数据
send_message = receive_message.upper().encode()  # 将客户端传来的字符串转为大写之后,再编码发送回客户端
conn.send(send_message)  # 发送数据给客户端
conn.close()  # 关闭连接
s.close() 
#!/usr/bin/env python
# -*- coding:utf-8 -*-

""" 客户端 """

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建客户端Socket
s.connect(('127.0.0.1', 8888))  # 连接客户端Socket到服务器ip和端口
print(s.getsockname())  # 打印客户端Socket的地址
send_message = 'Hello, world!'
s.send(send_message.encode())  # 发送数据给服务器
receive_message = s.recv(1024).decode()  # 接收服务器传来的数据并解码
print("Message received: {}".format(receive_message))  # 打印服务器传来的数据
s.close()  # 关闭连接

Run the server script first, and then run the client script, the results are as follows:

""" 服务器 """

Waiting connection from client...
Connected by ('127.0.0.1', 52161)
Message received: Hello, world!
""" 客户端 """

('127.0.0.1', 52161)
Message received: HELLO, WORLD!

The following points need to be noted here:
1. We use the new Socket (called service Socket or connection Socket) returned by the socket.accept() method to communicate with the client, not the server Socket (called listening Socket )itself. For details about monitoring Socket and service Socket/connection Socket, please refer to [13] and [14] .

2. After Python3, the socket transfers data of type bytes. The string needs to be converted first, and string.encode() is enough; the bytes data received by the other end needs to be converted into a string, as long as bytes.decode() Just do it [11] .


4.2 General idea of ​​Socket programming based on UDP

Compared with TCP-based Socket programming, UDP-based Socket programming is simpler. Since UDP does not have the process of handshaking and waving of TCP, the socket.listen(), socket.accept() and socket.connect()/socket.connect_ex() methods are not needed.

server :

  • Create server Socket: socket.socket(type=socket.SOCK_DGRAM)
  • Bind the created server Socket to an ip and port: socket.bind()
  • Receive data from the client, or send data to the client: socket.recvfrom(), or socket.sendto()
  • Close the connection: socket.close()

client :

  • Create client Socket: socket.socket(type=socket.SOCK_DGRAM)
  • Receive data from the server, or send data to the server: socket.recvfrom(), or socket.sendto()
  • Close the connection: socket.close()

The above process and the difference with TCP-based Socket programming can be summarized as shown in Figure 5 below:
insert image description here

insert image description here

Figure 5. Comparison of TCP-based Socket programming and UDP-based Socket programming. The figure above is the flow chart of Socket programming based on TCP, and the figure below is the flow chart of Socket programming based on UDP. [15]
 

Let's take daily texting as an example, and first understand the general idea of ​​UDP-based Socket programming visually and intuitively. If you are interested, you can learn more about the UDP protocol.

Server - equivalent to the SMS receiving party :

  • Create a server socket: It is equivalent to buying a mobile phone according to the network standard, 3G mobile phone, 4G mobile phone or 5G mobile phone?
  • Bind the created server Socket to an ip and port: it is equivalent to buying a phone card, and you can contact the designated person through this number.
  • Receive data from the client, or send data to the client: equivalent to sending and receiving text messages.
  • Close connection: It is equivalent to turning off the mobile phone.

Client - equivalent to the sending side :

  • Create a client socket: it is equivalent to buying a mobile phone according to the network standard, 3G mobile phone, 4G mobile phone or 5G mobile phone?
  • Receive data from the server, or send data to the server: equivalent to sending and receiving text messages.
  • Close connection: It is equivalent to turning off the mobile phone.

Unlike making a phone call, we send and receive text messages every day. It is not necessary for the two parties to establish a connection first. Instead, one party sends a text message to the other party, and the other party returns after receiving the text message. The client Socket sends the message to the server Socket with the corresponding address by specifying the address parameter through the socket.sendto() method, which is equivalent to entering the other party's mobile phone number when sending a text message. Then the server Socket receives the message through the socket.recvfrom() method and returns the address of the other party. This is equivalent to when we receive a text message from someone else, the mobile phone will not only display the content of the text message sent by the other party, but also display The other party's mobile phone number. In this way, the server Socket can send a message to the client by specifying the address parameter through the socket.sendto() method, which is equivalent to returning a message to the other party's mobile phone number.

Next, let's take the following code as an example to further understand the general idea of ​​the above-mentioned UDP-based Socket programming.

#!/usr/bin/env python
# -*- coding:utf-8 -*-

""" 服务器 """

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 创建服务器Socket
s.bind(('127.0.0.1', 8888))  # 绑定创建的服务器Socket到一个ip和端口
receive_message, address = s.recvfrom(1024)  # 接收客户端传来的数据
print("Receive message from {}".format(address))  # 打印客户端Socket的地址
receive_message = receive_message.decode()  # 解码客户端传来的数据
print("Message received: {}".format(receive_message))  # 打印客户端传来的数据
send_message = receive_message.upper().encode()  # 将客户端传来的字符串转为大写之后,再编码发送回客户端
s.sendto(send_message, address)  # 发送数据给客户端
s.close()  # 关闭连接
#!/usr/bin/env python
# -*- coding:utf-8 -*-

""" 客户端 """

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 创建客户端Socket
send_message = 'Hello, world!'
s.sendto(send_message.encode(), ('127.0.0.1', 8888))  # 发送数据给服务器
print(s.getsockname())  # 打印客户端Socket的地址
receive_message, address = s.recvfrom(1024)  # 接收服务器传来的数据
print("Receive message from {}".format(address))  # 打印服务器Socket的地址
receive_message = receive_message.decode()  # 解码服务器传来的数据
print("Message received: {}".format(receive_message))  # 打印服务器传来的数据
s.close()  # 关闭连接

Run the server script first, and then run the client script, the results are as follows:

""" 服务器 """

Receive message from ('127.0.0.1', 64410)
Message received: Hello, world!
""" 客户端 """

('0.0.0.0', 64410)
Receive message from ('127.0.0.1', 8888)
Message received: HELLO, WORLD!

Reference

[1]: https://baike.baidu.com/item/%E5%A5%97%E6%8E%A5%E5%AD%97/9637606?fr=aladdin
[2]: https://baike.baidu.com/item/TCP/IP%E5%8D%8F%E8%AE%AE/212915
[3]: https://www.runoob.com/tcpip/tcpip-tutorial.html
[4]: https://www.cnblogs.com/jukaiit/p/6775404.html
[5]: https://www.jianshu.com/p/8c1f37361a89
[6]: https://zhuanlan.zhihu.com/p/137212690
[7]: https://www.runoob.com/python/python-socket.html
[8]: https://blog.51cto.com/xpleaf/1700032
[9]: https://researchlab.github.io/2018/09/20/socket-concept/
[10]: https://docs.python.org/3.10/library/socket.html#socket.socket
[11]: https://www.liujiangblog.com/course/python/76
[12]: https://blog.csdn.net/pashanhu6402/article/details/96428887
[13]: https://blog.csdn.net/phunxm/article/details/5085825
[14]: https://www.cnblogs.com/freebrid/p/4703096.html
[15]: https://zhuanlan.zhihu.com/p/73514975

Guess you like

Origin blog.csdn.net/Graduate2015/article/details/122209859