1, tcp basic syntax
The server communicates with the client through socket. In order to ensure data integrity, tcp protocol needs to shake hands three times, and can only communicate with one client at a time
Server side writing method:
# Server #Import socket module import socket #Create socket object sk=socket.socket() #Bind server IP port sk.bind(("127.0.0.1",8080)) #Enable server listening status sk.listen() #Create tcp triple handshake (conn is the established two-way connection object) conn,addr=sk.accept() #Receive data (the maximum allowable transmission size is 1024 bytes) res=conn.recv(1024) print(res.decode("utf-8")) #Turn off two-way connection conn.close() #Close socket object sk.close()
Client writing:
# client #Import socket module import socket #Generate socket object sk=socket.socket() #Establish connection with the server sk.connect(("127.0.0.1",8080)) #send message sk.send("It rained heavily in Beijing yesterday".encode("utf-8")) #Close socket sk.close()
Operation results:
2, tcp circular message sending
The while loop needs to be introduced to send messages circularly to realize the online chat function
Server:
# Server # Import socket module import socket #Create socket object sk=socket.socket() #Bind server address and port sk.bind(("127.0.0.1",8090)) #Listening port sk.listen() #Receiving and sending data while True: conn,addr=sk.accept() while True: res=conn.recv(1024) print(res.decode()) strvar=input("Please enter a message to send to the client:") conn.send(strvar.encode()) if strvar.upper() == "Q": break #Turn off bidirectional connection object conn.close() #Close socket object sk.close()
client:
# client #Import socket module import socket #Create socket object sk=socket.socket() #Connect server sk.connect(("127.0.0.1",8090)) #Sending and receiving data while True: strvar=input("Please enter the information sent to the server:") sk.send(strvar.encode()) res=sk.recv(1024) print(res.decode()) if res == b"q" or res == b"Q": break sk.close()
Operation results:
Server:
client:
3, udp basic syntax
Server:
# Server # Import socket object import socket # When you create a socket object, you need to add parameters because the default is to create a tcp connection sk=socket.socket(type=socket.SOCK_DGRAM) # Bind server address and port sk.bind(("127.0.0.1",9005)) # receive data msg,cli_addr=sk.recvfrom(1024) print(msg.decode()) # send data strvar="Welcome" sk.sendto(strvar.encode(),cli_addr) #Close socket object sk.close()
client:
# client import socket #Create socket object sk=socket.socket(type=socket.SOCK_DGRAM) #send data sk.sendto("Hello".encode(),("127.0.0.1",9005)) #receive data msg,server_addr=sk.recvfrom(1024) print(msg.decode()) #Close connection sk.close()
Operation results:
Server:
client:
4, udp circular message sending
Under udp protocol, the server can communicate with multiple clients
Server:
# Server import socket sk=socket.socket(type=socket.SOCK_DGRAM) sk.bind(("127.0.0.1",9010)) while True: msg,cli_addr=sk.recvfrom(1024) print(msg.decode()) strvar=input("Please enter a message to send to the client:") sk.sendto(strvar.encode(),cli_addr) sk.close()
Client 1:
# client import socket sk=socket.socket(type=socket.SOCK_DGRAM) while True: strvar=input("Please enter the message to be sent to the server:") sk.sendto(strvar.encode(),("127.0.0.1",9010)) msg,server_addr=sk.recvfrom(1024) print(msg.decode()) sk.close()
Client 2:
# client import socket sk=socket.socket(type=socket.SOCK_DGRAM) while True: strvar=input("Please enter the message to be sent to the server:") sk.sendto(strvar.encode(),("127.0.0.1",9010)) msg,server_addr=sk.recvfrom(1024) print(msg.decode()) sk.close()
Operation results:
Server running result:
Client 1 running result:
Client 2 running result:
5, Sticky bag
1. Sticky bag
First, let's look at a situation:
Server:
# Server import socket sk=socket.socket() sk.bind(("127.0.0.1",8080)) sk.listen() conn,addr=sk.accept() conn.send("Hello".encode()) conn.send("Welcome".encode()) conn.close() sk.close()
client:
# client import socket sk=socket.socket() sk.connect(("127.0.0.1",8080)) res1=sk.recv(1024) print(res1.decode(),"<1>") res2=sk.recv(1024) print(res2.decode(),"<2>") sk.close()
Operation results:
As shown in the figure, the "welcome" string that should have been output in the second line and the "hello" string in the first line are output by adhesion. This phenomenon is called sticky package
There are two cases of sticking:
- Sticking phenomenon I:
At the transmitting end, because the two data are short and the transmission time interval is short, sticky packets are formed at the transmitting end - Sticking phenomenon II:
At the receiving end, since the two data are sent to each other's cache almost at the same time, all sticky packets are formed at the receiving end
Comparison of sticky packets: tcp and udp
tcp protocol:
Disadvantages: there is no boundary between the data when receiving. It is possible to glue several pieces of data into one piece of data, resulting in sticky packets
Advantages: the size of data packets is not limited, and the transmission is stable without packet loss
udp protocol:
Advantages: there are boundaries between data when receiving, fast transmission speed and no sticky packets
Disadvantages: limit the size of data packets (affected by factors such as bandwidth router), unstable transmission and possible packet loss
2. struct module
Application scenario:
- Solve the sticky package scenario:
During real-time communication in the application scenario, you need to read the message sent this time - There is no need to solve the sticky package scenario:
When downloading or uploading files, finally combine the packages together. It doesn't matter to stick the package
pack:
Converts a number of arbitrary length into a byte stream with a fixed length of 4 bytes
Package range: - 2147483648 ~ 2147483647 about 2.1 billion
unpack:
I = > convert the corresponding data to int integer
Restore the four byte value to the original number and return the final tuple
Server:
# Server import socket import struct sk=socket.socket() sk.bind(("127.0.0.1",8080)) sk.listen() conn,addr=sk.accept() strvar="Hello".encode() res1=len(strvar) num=struct.pack("i",res1) #4-bit byte stream transmitted for the first time conn.send(num) #Real byte stream transmitted for the second time conn.send(strvar) conn.send("Welcome".encode()) conn.close() sk.close()
client:
# client import socket import struct sk=socket.socket() sk.connect(("127.0.0.1",8080)) res1=sk.recv(1024) #Unpack, n is the real length of the incoming data n=struct.unpack("i",res1) #The boundary is stuck according to the real length of the string. Note that n is a tuple res2=sk.recv(n[0]) print(res2.decode(),"<1>") res3=sk.recv(1024) print(res3.decode(),"<2>") sk.close()
Client running result:
Because the boundary is blocked by the struct module in the first packet transmission, there will be no packet sticking