Home  >  Article  >  Web Front-end  >  Two ways to solve the problem of TCP sticky packets

Two ways to solve the problem of TCP sticky packets

little bottle
little bottleforward
2019-04-30 11:21:003979browse

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.

Part One: Introduction to the underlying principles of tcp socket communication

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.

Part 2: Reasons for sticky packets (only for tcp)

There are two situations where sticky packets occur:

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

Part 3: How to solve the above two Sticky bag phenomenon?

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!

Statement:
This article is reproduced at:cnblogs.com. If there is any infringement, please contact admin@php.cn delete