Socket socket programming
Today's Content
- Socket socket programming
- Simple Server-side and Client-side Code Implementation
- Communication Cycle
- Sticky phenomena (TCP protocol)
- Header making, struct module, encapsulation
Detailed Content
1. Socket socket programming
Implement a program that can interact with data.
When they communicate with each other, they have to transfer data through the network, which will certainly involve the operation of the OSI seven-layer protocol. Each time they transfer data, they need to operate the OSI seven-layer protocol, and they will repeat many similar tasks. At this time, socket module appears, encapsulating the operation code of the OSI seven-layer protocol. When we transfer data, we can see that The socket instantiated object can be used to call the operation method quickly and conveniently in the form of a point.
- socket module
Next, I'll use the socket module to implement the simplest socket programming.
Note: Only when the server is started can the client successfully connect to the server to achieve data exchange.
Server
import socket # Instantiate a socket object server = socket.socket() # Bind an IP +port number to'server (application)'as a unique identity server.bind(('192.168.11.134', 8080)) # Set up a semi-connection pool with a maximum capacity (number of connections waiting) of 5 server.listen(5) # Listen, when a client requests a connection, get its socket object and application address (IP+port) sock, address = server.accept() # receive data data = sock.recv(1024) print(data.decode('utf8')) # send data sock.send('elijah is very good'.encode('utf8')) # Close socket object connected to client sock.close() # Close the server's own socket object server.close()
Client
import socket # Instantiate the client's socket object client = socket.socket() # Clients connect precisely to servers based on IP+port client.connect(('192.168.11.134', 8080)) # Send data to server client.send('i am client'.encode('utf8')) # Receive data returned by the server data = client.recv(1024) print(data.decode('utf8')) # Close Client client.close()
2. Communication Cycle
Upgrade the Easy Version so that both the server and the client can enter customized information, and do not end the process as soon as the data is transferred, leaving the server listening and ready to connect with the client.
Server
import socket # Instantiate a socket object server = socket.socket() # Bind an IP +port number to'server (application)'as a unique identity server.bind(('192.168.11.134', 8080)) # Set up a semi-connection pool with a maximum capacity (number of connections waiting) of 5 server.listen(5) # Listen, when a client requests a connection, get its socket object and application address (IP+port) sock, address = server.accept() while True: # receive data client_data = sock.recv(1024) print(client_data.decode('utf8')) # send data server_data = input('Enter your reply>>>: ') sock.send(server_data.encode('utf8'))
Client
import socket # Instantiate the client's socket object client = socket.socket() # Clients connect precisely to servers based on IP+port client.connect(('192.168.11.134', 8080)) while True: # Send data to server client_data = input('Enter your information>>>: ') client.send(client_data.encode('utf8')) # Receive data returned by the server data = client.recv(1024) print(data.decode('utf8'))
Realize your one-sentence communication:
Code optimization
1,Keep the server listening. When the server replies to an empty message, it disconnects from the current client and returns to listening 2,The message sent by the client cannot be null (avoid both being present) revc Waiting State) 3,Add compatibility code on the server side ( mac linux) 4,Server restart frequently reported port occupancy error from socket import SOL_SOCKET, SO_REUSEADDR server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # Add before bind 5,Problem of client abnormal shutdown service side error Exception Capture 6.Service-side link loop 7.Semi Connection Pool Set the number of clients you can wait on (exceeding this number will cause an error)
Server
import socket # Instantiate a socket object server = socket.socket() # Bind an IP +port number to'server (application)'as a unique identity server.bind(('192.168.11.134', 8080)) # Set up a semi-connection pool with a maximum capacity (number of connections waiting) of 5 server.listen(5) while True: # Listen, when a client requests a connection, get its socket object and application address (IP+port) sock, address = server.accept() while True: # Handle client unexpected disconnection errors try: # receive data client_data = sock.recv(1024) print(client_data.decode('utf8')) # send data server_data = input('Enter your reply>>>: ') if len(server_data) == 0: break sock.send(server_data.encode('utf8')) except Exception as e: print(e) break
Client
import socket # Instantiate the client's socket object client = socket.socket() # Clients connect precisely to servers based on IP+port client.connect(('192.168.11.134', 8080)) while True: # Send data to server client_msg = input('Enter your information>>>: ') if len(client_msg) == 0: continue client.send(client_msg.encode('utf8')) # Receive data returned by the server data = client.recv(1024) print(data.decode('utf8'))
3. sticking problem
Since TCP is also a streaming protocol, data is streamed
When a client initiates a command request to the server, the server returns a large amount of data, while the client only receives 1024 bytes at a time. Obviously, the reception is incomplete, and the remaining data will not be lost, but will be blocked in the transmission channel. When the client next initiates the request command, the remaining data will flow in, causing unanswered questions to be answered.
TCP protocol has a feature
When sending less data, sending more than once, and sending at shorter intervals that TCP Automatically packages all this data into a single packet to receive sock.send('litle') sock.send('ll') sock.send('a') client.recv() client.recv() client.recv() ---> litlella
Solve sticking problem
- Make headlines
Headers are used to identify specific information about upcoming data
For example, the size of the data so that the recipient can decide how much data to receive based on the size of the data
client.recv(4343534)
Simple version header
import socket import subprocess import json import struct server = socket.socket() server.bind(('127.0.0.1', 8080)) server.listen(5) while True: sock, address = server.accept() while True: data = sock.recv(1024) # Receive cmd commands command_cmd = data.decode('utf8') sub = subprocess.Popen(command_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) res = sub.stdout.read() + sub.stderr.read() # The result may be great # 1. Make headlines data_first = struct.pack('i', len(res)) # 2. Send headers sock.send(data_first) # 3. Send real data sock.send(res) import socket import struct client = socket.socket() # Buy a mobile phone client.connect(('127.0.0.1', 8080)) # dial while True: msg = input('Please enter cmd command>>>:').strip() if len(msg) == 0: continue client.send(msg.encode('utf8')) # 1. Receive header data of a fixed length of 4 first recv_first = client.recv(4) # 2. Parse headers real_length = struct.unpack('i',recv_first)[0] # 3. Receive real data real_data = client.recv(real_length) print(real_data.decode('gbk'))
The header can be made into a dictionary so that in addition to receiving the specific size of the data, it can also receive more information about the data, and the'i'mode when strut is packaged will not cause the data to be too large and error
Expand knowledge
While reading the source code 1.A colon after a variable name means the type of data the variable name needs to refer to 2.The greater horizontal bar after the function is greater than the sign means the return value type of the function