1. 程式人生 > >socket 粘包

socket 粘包

輸入 server soc 循環調用 accept 服務 不知道 std bsp

產生粘包:

1.發送端需要等緩沖區滿才發送出去,造成粘包(發送數據時間間隔很短,數據了很小,會合到一起,產生粘包)

2.接收方不及時接收緩沖區的包,造成多個包接收(客戶端發送了一段數據,服務端只收了一小部分,

服務端下次再收的時候還是從緩沖區拿上次遺留的數據,產生粘包

所謂粘包問題主要還是因為接收方不知道消息之間的界限,不知道一次性提取多少字節的數據所造成的。

補充:

recv裏指定的1024意思是從緩存裏一次拿出1024個字節的數據

send的字節流是先放入己端緩存,然後由協議控制將緩存內容發往對端,如果待發送的字節流大小大於緩存剩余空間,那麽數據丟失,用sendall就會循環調用send,數據不會丟失

1.解決方法:

先發送消息的長度,再發送消息,接收的時候可以根據消息的長度循環取數據

或者發送的數據量比較小時,可以把消息加載在一個長字符串中傳遞,填充滿緩存

服務端:
#
_*_coding:utf-8_*_ from socket import * import subprocess import struct ip_port=(127.0.0.1,8080) BUFSIZE=1024 tcp_socket_server=socket(AF_INET,SOCK_STREAM) tcp_socket_server.bind(ip_port) tcp_socket_server.listen(
5) while True: conn,addr=tcp_socket_server.accept() print(客戶端,addr) while True: cmd=conn.recv(BUFSIZE) print(cmd.decode(utf-8)) if len(cmd) == 0:break res=subprocess.Popen(cmd.decode(utf-8),shell=True, #本地執行客戶端傳過來的命令 stdout
=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) stderr=res.stderr.read() if stderr: back_msg=stderr else: back_msg=res.stdout.read() print(len(back_msg)) conn.send(struct.pack(i,len(back_msg))) #先發送長度 i 4個字節 conn.sendall(back_msg) #再發送內容 # conn.close()
#_*_coding:utf-8_*_

import socket
import struct
BUFSIZE=100                    #故意設小一點,一次取不完
ip_port=(127.0.0.1,8080)

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res=s.connect_ex(ip_port)

while True:
    msg=input(>>: ).strip()              #輸入命令
    if len(msg) == 0:continue
    if msg == quit:break

    s.sendall(msg.encode(utf-8))
    head_info=s.recv(4)       #和服務端對應起來,pack i 是4個字節
    head_len=struct.unpack(i,head_info)[0]       #解壓pack的內容
    print("head_len",head_len)
    res=0
    data=b‘‘

    while res < head_len:            #循環取數據
        data+=s.recv(BUFSIZE)
        res=len(data)
        # print(‘res‘,res)
        # r_d=s.recv(BUFSIZE)
        # print(‘r_d‘,len(r_d))
        # data+=r_d
        # print(‘data‘,len(data))
        # res+=len(r_d)

    print(data.decode(gbk))

socket 粘包