中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

解決tcp粘包問題的辦法有哪些

發布時間:2020-07-21 09:46:03 來源:億速云 閱讀:311 作者:Leah 欄目:web開發

這篇文章將為大家詳細講解有關解決tcp粘包問題的辦法有哪些,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

第一部分:簡介tcp socket通信的底層原理

原理解析圖:

解決tcp粘包問題的辦法有哪些

1 socket通信過程如圖所示:首先客戶端將發送內容通過send()方法將內容發送到客戶端計算機的內核區,然后由操作系統將內容通過底層路徑發送到服務器端的內核區,然后由服務器程序通過recv()方法從服務器端計算機內核區取出數據。
2 因此我們可以了解到,send方法并不是直接將內容發送到服務器端,recv方法也并不是直接將從客戶端發來的內容接收到服務器程序內存中,而是操作自己機器的內核區。

第二部分:產生粘包的原因(只針對tcp)

產生粘包的情況有兩種:

1 1:當連續發送數據時,由于tcp協議的nagle算法,會將較小的內容拼接成大的內容,一次性發送到服務器端,因此造成粘包2 3 2:當發送內容較大時,由于服務器端的recv(buffer_size)方法中的buffer_size較小,不能一次性完全接收全部內容,因此在下一次請求到達時,接收的內容依然是上一次沒有完全接收完的內容,因此造成粘包現象。

也就是說:接收方不知道該接收多大的數據才算接收完畢,造成粘包。

相關教程:TCP/IP視頻教程

第三部分:如何解決上述兩種粘包現象?

思路一:對于第一種粘包產生方式可以在兩次send()直接使用recv()來阻止連續發送的情況發生。代碼就不用展示了。

思路二:由于產生粘包的原因是接收方的無邊界接收,因此發送端可以在發送數據之前向接收端告知發送內容的大小即可。代碼示例如下:

  方式一:分兩次通訊分別傳遞內容大小和內容

  服務器端代碼:

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

  方式二:一次通訊直接傳遞內容大小和內容

  服務器端:

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

關于解決tcp粘包問題的辦法有哪些就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

贵定县| 重庆市| 峨山| 宝丰县| 沙洋县| 丹江口市| 新疆| 沐川县| 唐河县| 柳河县| 龙里县| 东明县| 辽宁省| 巴东县| 藁城市| 登封市| 南木林县| 宜阳县| 老河口市| 杂多县| 卢龙县| 新沂市| 阳春市| 从江县| 乌什县| 昌吉市| 盐池县| 尉犁县| 水城县| 九龙坡区| 栾川县| 神农架林区| 蕲春县| 台南县| 屏山县| 淅川县| 神池县| 安顺市| 五河县| 西贡区| 尉氏县|