1. 程式人生 > >31 socket套接字 struct模塊

31 socket套接字 struct模塊

exce 問題 error: linux mac系統 pip 訪問 roc 間隔

socket(套接字)
  基於socket實現客戶端與服務端通信

服務端套接字函數

s.bind() 綁定(主機,端口號)到套接字

s.listen() 開始TCP監聽

s.accept() 被動接受TCP客戶的連接,(阻塞式)等待連接的到來

客戶端套接字函數

s.connect() 主動初始化TCP服務器連接

s.connect_ex() connect()函數的擴展版本,出錯時返回出錯碼,而不是拋出異常

公共用途的套接字函數

s.recv() 接收TCP數據

s.send() 發送TCP數據(send在待發送數據量大於己端緩存區剩余空間時,數據丟失,不會發完)

socket初識

  127.0.0.1:本地回環地址,只能本機訪問

-----------------------------服務端------------------------------
import socket

server = socket.socket()  # 類似於買手機
server.bind((127.0.0.1, 8080))  # 類似於插手機卡   bind((IP,PORT))
server.listen(5)  # 開機   半連接池

conn, addr = server.accept()  # 待機等待接電話

data 
= conn.recv(1024) # 接聽別人說話 只接收1024個字節 bytes print(data) conn.send(bhello!) # 跟別人說話 conn.close() # 關閉通信連接 server.close() # 關閉服務端 -----------------------------客戶端------------------------------ import socket client = socket.socket() client.connect((127.0.0.1, 8080)) # 找服務器 client.send(b
hello how much?) data = client.recv(1024) print(data) client.close()

TCP協議的特點

  會將數據量比較小的,並且時間間隔比較短的數據,一次性打包發送給接收端

-----------------------------服務端------------------------------
import socket

server = socket.socket()
server.bind((127.0.0.1,8088))
server.listen(5)  # 半連接池


conn,addr = server.accept()
data = conn.recv(1024)
print(data)
data = conn.recv(1024)
print(data)
data = conn.recv(1024)
print(data)

>>>:bhellohellohello
   b‘‘
   b‘‘


-----------------------------客戶端------------------------------
import socket

client = socket.socket()
client.connect((127.0.0.1,8088))


client.send(bhello)
client.send(bhello)
client.send(bhello)            

通信循環

-----------------------------服務端------------------------------
import socket

"""
服務端:
要有固定的ip和port
24小時不間斷提供服務
"""
server = socket.socket()
server.bind((127.0.0.1, 8080))
server.listen(5)

conn, addr = server.accept()  # 阻塞

while True:
    try:
        data = conn.recv(1024)  # 阻塞
        if len(data) == 0: break  # 針對linux和mac系統 客戶端異常斷開反復收空的情況
        print(data)
        conn.send(data.upper())
    except ConnectionResetError:
        break

conn.close()
server.close()


-----------------------------客戶端------------------------------
import socket

client = socket.socket()
client.connect((127.0.0.1, 8080))

while True:
    msg = input(>>>:).encode(utf-8)
    if len(msg) == 0: continue
    client.send(msg)
    data = client.recv(1024)
    print(data)

struct模塊

import struct

data = seionksngjgm,xmdnabnk ko
res = struct.pack(i,len(data))

print(res:,res)   # res: b‘\x18\x00\x00\x00‘
print(len(res):,len(res))  # 4


ret = struct.unpack(i,res)
print(ret:,ret)  # (24,)
print(ret[0]:,ret[0])  # 24

鏈接循環

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

"""
服務端:
要有固定的ip和port
24小時不間斷提供服務
"""
server = socket.socket()
server.bind((127.0.0.1, 8081))
server.listen(5)  # 半連接池

while True:
    conn, addr = server.accept()  # 阻塞
    while True:
        try:
            data = conn.recv(1024).decode(utf-8)  # 阻塞
            if len(data) == 0: break  # 針對linux和mac系統 客戶端異常斷開反復收空的情況
            obj = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout = obj.stdout.read()
            stderr = obj.stderr.read()
            print(len(stdout + stderr))

            header_dic = {
                filename: cls.av,
                len: len(stdout + stderr)
            }
            header_bytes = json.dumps(header_dic).encode(utf-8)
            # 制作報頭
            header = struct.pack(i, len(header_bytes))  # 將需要發送給客戶端的數據打包成固定4個字節
            conn.send(header)

            conn.send(header_bytes)

            conn.send(stdout + stderr)

        except ConnectionResetError:
            break
    conn.close()

server.close()



-----------------------------客戶端------------------------------
import socket
import struct
import json

client = socket.socket()
client.connect((127.0.0.1, 8081))

while True:
    msg = input(>>>:).encode(utf-8)
    if len(msg) == 0: continue
    client.send(msg)
    header = client.recv(4)
    # 對這個頭進行解包,獲取真實數據的長度

    head_len = struct.unpack(i, header)[0]
    head_dic = json.loads(client.recv(head_len).decode(utf-8))
    print(head_dic)
    # 對需要接受的數據 進行循環接收
    total_size = head_dic[len]
    recv_size = 0
    res = b‘‘
    while recv_size < total_size:
        data = client.recv(1024)
        res += data
        recv_size += len(data)
    print(res.decode(gbk))

粘包問題

-----------------------------服務端------------------------------
import socket

"""
服務端:
要有固定的ip和port
24小時不間斷提供服務
"""
server = socket.socket()
server.bind((127.0.0.1, 8080))
server.listen(5)  # 半連接池

while True:
    conn, addr = server.accept()  # 阻塞
    while True:
        try:
            data = conn.recv(1024)  # 阻塞
            if len(data) == 0: break  # 針對linux和mac系統 客戶端異常斷開反復收空的情況
            print(data)
            conn.send(data.upper())
        except ConnectionResetError:
            break
    conn.close()

server.close()



-----------------------------客戶端------------------------------
import socket

client = socket.socket()
client.connect((127.0.0.1, 8080))

while True:
    msg = input(>>>:).encode(utf-8)
    if len(msg) == 0: continue
    client.send(msg)
    data = client.recv(1024)
    print(data)

最終方法:解決粘包問題
1.先發報頭
2.再發字典
3.再發你的真實數據


1.先收4個長度的報頭
2.解包拿到字典數據長度
3.接收字典(反序列化) 》》》 獲取字典裏面所有信息
4.接收真實數據

31 socket套接字 struct模塊