Heim  >  Artikel  >  Web-Frontend  >  Zwei Möglichkeiten, das Problem der TCP-Sticky-Pakete zu lösen

Zwei Möglichkeiten, das Problem der TCP-Sticky-Pakete zu lösen

little bottle
little bottlenach vorne
2019-04-30 11:21:003978Durchsuche

In diesem Artikel geht es hauptsächlich darum, wie das TCP-Sticky-Problem gelöst werden kann. Das erste besteht darin, die Inhaltsgröße und den Inhalt in zwei Kommunikationen zu übertragen. Freunde, die mehr wissen möchten, können diesen Artikel ausführlich lesen. Ich hoffe, er wird Ihnen hilfreich sein.

Teil 1: Einführung in die zugrunde liegenden Prinzipien der TCP-Socket-Kommunikation

Prinzipanalysediagramm:

1 Der Socket-Kommunikationsprozess ist wie in der Abbildung dargestellt: Zuerst sendet der Client den Inhalt über die send()-Methode an den Kernelbereich des Clientcomputers, und dann sendet das Betriebssystem den Inhalt Inhalte werden über den zugrunde liegenden Pfad in den Kernelbereich des Servers übertragen. Anschließend ruft das Serverprogramm die Daten über die recv()-Methode aus dem Kernelbereich des Servercomputers ab.
2 Daher können wir verstehen, dass die Sendemethode den Inhalt nicht direkt an den Server sendet und die Recv-Methode den vom Client gesendeten Inhalt nicht direkt in den Serverprogrammspeicher empfängt, sondern ihren eigenen Kernel betreibt Maschine.

Teil 2: Gründe für Sticky-Pakete (nur für TCP)

Es gibt zwei Situationen, in denen Sticky-Pakete auftreten:

1 1: Beim kontinuierlichen Senden von Daten. Aufgrund der Durch den Nagle-Algorithmus des TCP-Protokolls werden kleinere Inhalte in große Inhalte gespleißt und sofort an den Server gesendet, wodurch Sticky-Pakete entstehen. 2 3 2: Wenn der gesendete Inhalt groß ist, liegt dies an der Methode recv (buffer_size). serverseitig Die buffer_size ist klein und kann nicht den gesamten Inhalt auf einmal empfangen. Wenn die nächste Anforderung eintrifft, ist der empfangene Inhalt daher immer noch der Inhalt, der beim letzten Mal nicht vollständig empfangen wurde, was das Sticky-Phänomen verursacht.

Das heißt: Der Empfänger weiß nicht, wie viele Daten er empfangen soll, bevor er vollständig empfangen wird, was zu Sticky-Paketen führt.

Verwandte Tutorials: TCP/IP-Video-Tutorial

Teil 3: So lösen Sie die beiden oben genannten Probleme Probleme Sticky-Bag-Phänomen?

Idee 1: Für die erste Sticky-Packet-Generierungsmethode können Sie recv() direkt in zwei send()s verwenden, um ein kontinuierliches Senden zu verhindern. Es ist nicht erforderlich, den Code anzuzeigen.

Idee 2: Da Sticky Packets durch den unbegrenzten Empfang des Empfängers verursacht werden, kann der Sender den Empfänger vor dem Senden der Daten über die Größe des Inhalts informieren. Das Codebeispiel lautet wie folgt:

Methode 1: Übergeben Sie die Inhaltsgröße und den Inhalt jeweils in zwei Kommunikationen

Servercode:

# __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-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"))

 Methode 2: Inhaltsgröße und Inhalt direkt in einer Kommunikation übertragen

Serverseite:

# __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

 Kunde:

# __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"))

Beide der beiden oben genannten Methoden können das Sticky-Problem lösen.

Das obige ist der detaillierte Inhalt vonZwei Möglichkeiten, das Problem der TCP-Sticky-Pakete zu lösen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen