1. 程式人生 > >Socket傳輸簡單的信息以及粘包問題的解決

Socket傳輸簡單的信息以及粘包問題的解決

strip() hide error img author 圖片 ack 傳輸 accept

  一、簡單的socket程序——傳輸簡短文字:

技術分享圖片
# -*- coding: utf-8  -*-
# -*- Author: WangHW -*-
import socket

whw_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
whw_client.connect((127.0.0.1,9001))
while 1:
    cmd = input(>>>:).strip()
    if not cmd:
        continue
    whw_client.send(cmd.encode(
utf-8)) recv_data = whw_client.recv(1024) data = recv_data.decode(utf-8) print(server data:,data)
client 技術分享圖片
# -*- coding: utf-8  -*-
# -*- Author: WangHW -*-
import socket

whw_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
whw_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,
1) whw_server.bind((127.0.0.1,9001)) whw_server.listen(5) print(listening......) conn,addr = whw_server.accept() #通信循環 while 1: try: recv_data = conn.recv(1024) data = recv_data.decode(utf-8) print(client data:,data) conn.send(data.swapcase().encode(utf-8))
except ConnectionResetError: break conn.close()
server

  演示如下:

技術分享圖片

二、模擬SSH命令——解決粘包問題版:

  關於粘包問題的解決方案:

  在服務器端,由於解析出來的命令結果非常多,所以我們在發送結果之前需要先給客戶端發送一個“報文”,這個報文保存著具體的命令結果的信息——其中關鍵的信息就是結果的長度,客戶端只有知道這個結果的長度後,才能制定相應的接收規則:

技術分享圖片
# -*- coding: utf-8  -*-
# -*- Author: WangHW -*-
import socket
import json
import struct

whw_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
whw_client.connect((127.0.0.1,9000))
while 1:
    try:
        cmd = input(>>>:).strip()
        if not cmd:
            continue
        #發命令
        whw_client.send(cmd.encode(utf-8))
        #1.收報頭長度
        obj = whw_client.recv(10)
        #註意structunpack出來的[0]值為長度信息
        header_size = struct.unpack(i,obj)[0]
        #2.收報頭——根據報頭長度來收
        header_bytes = whw_client.recv(header_size)
        #3.從報頭中解析出‘total_size‘
        header_json = header_bytes.decode(utf-8)
        header_dic = json.loads(header_json)
        total_size = header_dic[total_size]
        #根據total_size開始接收真實的數據
        recv_size = 0
        recv_data = b‘‘
        while recv_size < total_size:
            res = whw_client.recv(1024)
            recv_data += res
            recv_size += len(res)
        print(命令結果:\n,recv_data.decode(gbk))
    except Exception as e:
        whw_client.close()
client 技術分享圖片
# -*- coding: utf-8  -*-
# -*- Author: WangHW -*-
import socket
import subprocess
import json
import struct

whw_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
whw_server.bind((127.0.0.1,9000))
whw_server.listen(5)
print(Listening......)
conn,addr = whw_server.accept()
while 1:
    try:
        #收命令
        cmd_recv = conn.recv(1024).decode(utf-8)
        #解析命令
        obj = subprocess.Popen(cmd_recv,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        stdout = obj.stdout.read()
        stderr = obj.stderr.read()
        #將命令返回給客戶端
        #1.制作固定報頭——註意報頭裏面要包含數據的總長度!
        header_dic = {filename:whw,total_size:len(stdout)+len(stderr)}
        header_json = json.dumps(header_dic)
        header_bytes = header_json.encode(utf-8)
        #2.發送報頭長度——struct:把數字打成固定長度
        conn.send(struct.pack(i,len(header_bytes)))
        #3.發送報頭
        conn.send(header_bytes)
        #4.發送真實數據
        conn.send(stdout)
        conn.send(stderr)
    except ConnectionResetError:
        break

conn.close()
server

  演示如下:

技術分享圖片

Socket傳輸簡單的信息以及粘包問題的解決