Maison  >  Article  >  interface Web  >  Deux façons de résoudre le problème des paquets persistants TCP

Deux façons de résoudre le problème des paquets persistants TCP

little bottle
little bottleavant
2019-04-30 11:21:003955parcourir

Cet article explique principalement comment résoudre le problème du sticky TCP. La première consiste à transférer respectivement la taille et le contenu du contenu. La seconde consiste à transmettre directement la taille et le contenu du contenu en une seule communication. Les amis qui souhaitent en savoir plus peuvent lire cet article en détail, j'espère qu'il vous sera utile.

Partie 1 : Introduction aux principes sous-jacents de la communication par socket TCP

Schéma d'analyse des principes :

1 Le processus de communication du socket est comme indiqué sur la figure : d'abord, le client enverra le contenu à la zone noyau de l'ordinateur client via la méthode send(), puis le système d'exploitation enverra le contenu vers la zone noyau du serveur via le chemin sous-jacent. Le programme serveur récupère ensuite les données de la zone noyau de l'ordinateur serveur via la méthode recv().
2 Par conséquent, nous pouvons comprendre que la méthode send n'envoie pas directement le contenu au serveur, et que la méthode recv ne reçoit pas directement le contenu envoyé par le client dans la mémoire du programme du serveur, mais exploite son propre noyau quartier des machines.

Partie 2 : Raisons des paquets collants (uniquement pour TCP)

Il existe deux situations dans lesquelles des paquets collants se produisent :

1 1 : Lors de l'envoi de données en continu, en raison de Nagle du protocole TCP, le contenu plus petit sera fusionné en contenu volumineux et envoyé au serveur immédiatement, provoquant ainsi des paquets collants 2 3 2 : Lorsque le contenu envoyé est volumineux, en raison de la méthode recv (buffer_size) sur le côté serveur La taille du tampon est petite et ne peut pas recevoir complètement tout le contenu en même temps. Par conséquent, lorsque la requête suivante arrive, le contenu reçu est toujours le contenu qui n'a pas été complètement reçu la dernière fois, provoquant ainsi le phénomène de collage de paquets.

C'est-à-dire : Le récepteur ne sait pas combien de données il doit recevoir avant qu'elles ne soient complètement reçues, ce qui entraîne des paquets collants.

Tutoriels associés : Tutoriel vidéo TCP/IP

Partie 3 : Comment résoudre les deux problèmes ci-dessus problèmes Phénomène de sac collant ?

Idée 1 : Pour la première méthode de génération de paquets persistants, vous pouvez utiliser directement recv() dans deux send() pour empêcher l'envoi continu. Il n'est pas nécessaire de montrer le code.

Idée 2 : Puisque les paquets collants sont causés par la réception illimitée du destinataire, l'expéditeur peut informer le destinataire de la taille du contenu avant d'envoyer les données. L'exemple de code est le suivant :

Méthode 1 : Transmettre la taille du contenu et le contenu dans deux communications respectivement

Code serveur :

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

 Code client :

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

 Méthode 2 : Transférer directement la taille et le contenu du contenu en une seule communication

Côté serveur :

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

Les deux méthodes ci-dessus peuvent résoudre le problème délicat.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer