ホームページ  >  記事  >  ウェブフロントエンド  >  TCP スティッキー パケットの問題を解決する 2 つの方法

TCP スティッキー パケットの問題を解決する 2 つの方法

little bottle
little bottle転載
2019-04-30 11:21:003979ブラウズ

この記事では主に、TCP スティッキー パケットの問題を解決する方法について説明します。1 つ目は、コンテンツ サイズとコンテンツをそれぞれ 2 回の通信で転送する方法、2 つ目は、コンテンツ サイズとコンテンツを 1 回の通信で直接転送する方法です。もっと詳しく知りたい友達は、この記事を詳しく読んでみてください。お役に立てれば幸いです。

パート 1: TCP ソケット通信の基礎原理の紹介

原理分析図:

##1 ソケット通信プロセスを図に示します。まず、クライアントが send() メソッドを通じてクライアント コンピューターのカーネル領域にコンテンツを送信し、次にオペレーティング システムがコンテンツを送信します。基盤となるパスを介してサーバーのカーネル領域にデータを送信し、サーバー プログラムは、recv() メソッドを通じてサーバー コンピューターのカーネル領域からデータを取得します。

2 つまり、sendメソッドはサーバーにコンテンツを直接送信するのではなく、recvメソッドはクライアントからサーバーのプログラムメモリに送信されたコンテンツを直接受信するのではなく、自マシンのカーネルを動作させるということが分かります。 。 地区。

パート 2: スティッキー パケットの理由 (tcp のみ)

スティッキー パケットが発生する状況は 2 つあります:

1 1: データが継続的に送信される場合、 TCP プロトコルの nagle アルゴリズムでは、小さなコンテンツが大きなコンテンツに結合されて一度にサーバーに送信されるため、スティッキー パケットが発生します 2 3 2: 大きなコンテンツを送信するとき、サーバー側のbuffer_sizeが小さいため、一度にすべてのコンテンツを受信しきれないため、次のリクエストが来たときに受信コンテンツが前回受信しきれなかったコンテンツのままとなり、スティッキー現象が発生します。

つまり:

受信者は、受信が完了するまでにどれだけのデータを受信すべきかを知らないため、スティッキー パケットが発生します。

関連チュートリアル: TCP/IP ビデオ チュートリアル

パート 3: 上記 2 つの問題を解決する方法粘着バッグ現象?

アイデア 1: 最初のスティッキー パケットの生成方法では、2 つの send() で recv() を直接使用して、連続送信を防ぐことができます。コードを表示する必要はありません。

アイデア 2:

スティッキー パケットは受信者の無制限受信によって発生するため、送信者はデータを送信する前に受信者にコンテンツのサイズを通知できます。コード例は次のとおりです。

方法 1: コンテンツ サイズとコンテンツを 2 つの通信でそれぞれ渡します

サーバー側コード:

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

クライアント側コード:

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

## 方法 2: 1 回の通信でコンテンツのサイズと内容を直接送信する

##サーバー側:

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

クライアント:

# __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"))
上記 2 つの方法はどちらも厄介な問題を解決できます。

以上がTCP スティッキー パケットの問題を解決する 2 つの方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。