This article mainly talks about how to solve the problem of TCP sticky packets. The first is to transfer the content size and content in two communications respectively. The second is to directly transfer the content size and content in one communication. Friends who want to know more can read this article in detail. I hope it will be helpful to you.
Principle analysis diagram:
1 The socket communication process is shown in the figure: first, the client will send the content to the kernel area of the client computer through the send() method, and then the operating system will send the content to the kernel area of the server through the underlying path. The server program then retrieves the data from the kernel area of the server computer through the recv() method.
2 So we can understand that the send method does not directly send the content to the server, and the recv method does not directly receive the content sent from the client into the server program memory, but operates the kernel of its own machine. district.
1 1: When data is sent continuously, Due to the nagle algorithm of the tcp protocol, smaller content will be spliced into large content and sent to the server at one time, thus causing sticky packets 2 3 2: When sending large content, due to the recv (buffer_size) method on the server side The buffer_size is small and cannot completely receive all the content at once. Therefore, when the next request arrives, the received content is still the content that was not completely received last time, thus causing the sticky phenomenon.
That is to say: The receiver does not know how much data should be received before the reception is completed, resulting in sticky packets.
Related tutorials: TCP/IP video tutorial
Idea 1: For the first sticky packet generation method, you can directly use recv() in two send()s to prevent continuous sending. There is no need to show the code.
Idea 2: Since sticky packets are caused by the receiver’s unbounded reception, the sender can inform the receiver of the size of the content before sending the data. The code example is as follows:
Method 1: Pass the content size and content in two communications respectively
Server-side code:
# __author__:Kelvin # date:2019/4/28 21:36 from socket import * import subprocess server = socket(AF_INET, SOCK_STREAM) server.bind(("127.0.0.1", 8000)) server.listen(5) while True: conn, addr = server.accept() print("创建了一个新的连接!") while True: try: data = conn.recv(1024) if not data: break res = subprocess.Popen(data.decode("utf-8"), shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) err = res.stderr.read() if err: cmd_msg = err else: cmd_msg = res.stdout.read() if not cmd_msg: cmd_msg = "action success!".encode("gbk") length = len(cmd_msg) conn.send(str(length).encode("utf-8")) conn.recv(1024) conn.send(cmd_msg) except Exception as e: print(e) break
Client-side code:
# __author__:Kelvin # date:2019/4/28 21:36 from socket import * client = socket(AF_INET, SOCK_STREAM) client.connect(("127.0.0.1", 8000)) while True: inp = input(">>:") if not inp: continue if inp == "quit": break client.send(inp.encode("utf-8")) length = int(client.recv(1024).decode("utf-8")) client.send("ready!".encode("utf-8")) lengthed = 0 cmd_msg = b"" while lengthed < length: cmd_msg += client.recv(1024) lengthed = len(cmd_msg) print(cmd_msg.decode("gbk"))
Method 2: Directly transmit the content size and content in one communication
Server side:
# __author__:Kelvin # date:2019/4/28 21:36 from socket import * import subprocess import struct server = socket(AF_INET, SOCK_STREAM) server.bind(("127.0.0.1", 8000)) server.listen(5) while True: conn, addr = server.accept() print("创建了一个新的连接!") while True: try: data = conn.recv(1024) if not data: break res = subprocess.Popen(data.decode("utf-8"), shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) err = res.stderr.read() if err: cmd_msg = err else: cmd_msg = res.stdout.read() if not cmd_msg: cmd_msg = "action success!".encode("gbk") length = len(cmd_msg) conn.send(struct.pack("i", length)) conn.send(cmd_msg) except Exception as e: print(e) break
Client:
# __author__:Kelvin # date:2019/4/28 21:36 from socket import * import struct client = socket(AF_INET, SOCK_STREAM) client.connect(("127.0.0.1", 8000)) while True: inp = input(">>:") if not inp: continue if inp == "quit": break client.send(inp.encode("utf-8")) length = struct.unpack("i",client.recv(4))[0] lengthed = 0 cmd_msg = b"" while lengthed < length: cmd_msg += client.recv(1024) lengthed = len(cmd_msg) print(cmd_msg.decode("gbk"))
Both the above two methods can solve the sticky problem.
The above is the detailed content of Two ways to solve the problem of TCP sticky packets. For more information, please follow other related articles on the PHP Chinese website!