~~網絡編程(六):自定義報頭~~


進擊のpython

*****

網絡編程——自定義報頭


當你正在給你朋友顯擺你的代碼的時候, 飄過來一個大神隨口說道:“這代碼有問題”

大神說的話不能不當真啊,誰讓你是個菜雞,你仔細想了一會兒。嗯,確實有問題

首先,我剛才做的報頭,按照協議來說應該不只有長度信息,還應該有其他信息

其次就是這個struct模塊,它是有長度范圍限制的

struct.pack("i", 10000000000)

這樣就會報錯,因為你超過他長度了

這個經過百度,啊,知道了,還有另一種寫法

struct.pack("l", 10000000000)

這樣就不會報錯了,但是當我后面的數字是100000000000000000,還是報錯了

所以要針對這兩點,優化一下代碼,也就是自定義報頭


那別的地方都不用改動,我們就看報頭部分就行

首先報頭部分的信息用什么類型來存儲呢?最好是字典,因為字典有明確的映射關系

dic = {
    "file_name": "",
    "MD5": "XXXXXXXXXXXXXXXX",
    'file_size': en(stdout) + len(stderr)
}

好,字典就設定好了!但是,字典類型能用於數據傳輸嗎?

肯定是不能的啊,所以要把字典轉換成為字節模式才行

那要是這樣的話,我就想到了序列化!

head = json.dumps(dic)

json格式的字符串,能用來發送嗎?不能

所以還要編碼一下

head = head.encode("gbk")

然后就想到了struct模塊了,但是她只能接收數字是吧,所以我們可以把報頭的長度發過去

struct.pack("i", len(head))

然后再把報頭的信息發過去

connet.send(head)

最后再發真實數據,那服務端大概就是這樣做的

那客戶端呢????

我應該先解碼,然后反序列化,然后拿到的是字典

最后再通過字典來進行取值操作

那經過上面的分析,我們可以對代碼進行如下修改!

# 服務端
import json
import socket
import struct
import subprocess

# 買手機

phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 綁定手機卡
phone.bind(("127.0.0.1", 8080))
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 開機
phone.listen(5)

# 等電話
connet, client_addr = phone.accept()

# 收發消息
while 1:
    try:
        k = connet.recv(1024)
        obj = subprocess.Popen(k.decode("gbk"), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout = obj.stdout.read()
        stderr = obj.stderr.read()

        dic = {
            "file_name": "",
            "MD5": "XXXXXXXXXXXXXXXX",
            'file_size': len(stdout) + len(stderr)
        }
        head = json.dumps(dic)
        head = head.encode("gbk")
        res = struct.pack("i", len(head))
        connet.send(res)
        connet.send(head)

        connet.send(stdout)
        connet.send(stderr)
    except ConnectionResetError:
        break

# 掛電話
connet.close()

# 關機
phone.close()
# 客戶端
import json
import socket

# 買手機
import struct

phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 撥號
phone.connect(("127.0.0.1", 8080))

# 發收信息
while 1:
    msg = input(">>>")
    phone.send(msg.encode("gbk"))
    res = phone.recv(4)
    re_msg = struct.unpack("i", res)[0]
    msg = phone.recv(re_msg)
    msg = msg.decode("gbk")
    msg = json.loads(msg)
    re_len = msg["file_size"]
    re_size = 0
    r = b""  # 我傳過來的是字節模式
    while re_size < re_len:
        k = phone.recv(1024)
        r += k
        re_size += len(k)
        print(re_size, re_len)
    print(f'從服務端接收的消息:{r.decode("gbk")}')

connet.close()
# 關閉
phone.close()

這樣我們的這個C/S架構模式就基本成型了

以后的C/S架構就可以仿照這個模式來進行

至此,關於粘包問題的解決方案就告一段落了


*模板嘛*
*實在不行記下來嘛*


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM