扩大
缩小

いらっしゃいませ

4.缓冲区,黏包问题

缓冲区

将程序和网络解耦

什么是黏包

只有TCP有黏包现象,UTP永远没有黏包现象

两种黏包的现象:

1.连续的小包可会被优化算法给组合到一起进行发送

2.第一次如果发送的数据大小2000B接收端一次性接收大小为1024,这就是导致剩下的内容会被下一次recv接收到,导致结果混乱

第一种产生黏包,大于接收值时就会产生黏包

import socket

client = socket.socket()
client.connect(('127.0.0.1',8001))

while 1:
    cmd = input('请输入指令:')

    client.send(cmd.encode('utf-8'))

    server_cmd_result = client.recv(1024)

    print(server_cmd_result.decode('gbk'))
客户端
import socket
import subprocess
server = socket.socket()
ip_port = ('127.0.0.1',8001)

server.bind(ip_port)

server.listen()

conn,addr = server.accept()

while 1:
    from_client_cmd = conn.recv(1024)
    print(from_client_cmd.decode('utf-8'))
    sub_obj = subprocess.Popen(
        from_client_cmd.decode('utf-8'),
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )

    std_msg = sub_obj.stdout.read()
    print('指令的执行结果长度>>>>',len(std_msg))

    conn.send(std_msg)
服务端

第二种产生黏包,同时发生信息产生黏包

import socket
BUFSIZE = 1024
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res = s.connect(('127.0.0.1',8001))

s.send('hi'.encode('utf-8'))
s.send('alex'.encode('utf-8'))
客户端
from socket import *

tcp_socket_server = socket(AF_INET,SOCK_STREAM)
ip_port = ('127.0.0.1',8001)

tcp_socket_server.bind(ip_port)

tcp_socket_server.listen(5)

conn,addr = tcp_socket_server.accept()

data1 = conn.recv(10)
data2 = conn.recv(10)
print('----->',data1.decode('utf-8'))
print('----->',data2.decode('utf-8'))

conn.close()
服务端

解决方案一:由于双方不知道对方发送的长度,导致接收的时候可能接收不全,或者多接收另外一次发送的信息内容,所以所以在发送真实数据之前,要先发送数据长度,接收端根据长度接收后面真实数据,但是双方有一个交互确认的过程

import socket

client = socket.socket()
client.connect(('127.0.0.1',8001))

while 1:
    cmd = input('请输入指令:')

    client.send(cmd.encode('utf-8'))

    server_cmd_len = client.recv(1024).decode('utf-8')

    print('来自服务端的信息长度',server_cmd_len)
    client.send(b'ok')
    server_cmd_result = client.recv(int(server_cmd_len))
    print(server_cmd_result.decode('gbk'))
客户端
import socket
import subprocess
server = socket.socket()
ip_port = ('127.0.0.1',8001)

server.bind(ip_port)

server.listen()

conn,addr = server.accept()

while 1:
    from_client_cmd = conn.recv(1024)
    print(from_client_cmd.decode('utf-8'))
    sub_obj = subprocess.Popen(
        from_client_cmd.decode('utf-8'),
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )

    std_msg = sub_obj.stdout.read()
    std_msg_len = len(std_msg)
    std_bytes_len = str(len(std_msg)).encode("utf-8")
    print('指令的执行结果长度>>>>',len(std_msg))
    conn.send(std_bytes_len)

    status = conn.recv(1024)
    if status.decode('utf-8') == 'ok':
        conn.send(std_msg)
    else:
        pass
服务端

解决方案二: struct模块

打包:struct.pack('i',长度)

解包:struct.unpack('i',字节)

# -*- coding:utf-8 -*-
import socket
import struct

client = socket.socket()
client.connect(('127.0.0.1',8008))

while 1:
    cmd = input('请输入指令:')
    client.send(cmd.encode("utf-8"))
    server_res_len = client.recv(4)
    msg_len = struct.unpack('i',server_res_len)[0]
    print("来自服务端的信息长度:",msg_len)
    server_cmd_result = client.recv(msg_len)
    print(server_cmd_result.decode('gbk'))
客户端
# -*- coding:utf-8 -*-

import socket
import subprocess
import struct
server = socket.socket()
ip_port = ('127.0.0.1',8008)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
while 1:
    from_client_cmd = conn.recv(1024)
    print(from_client_cmd.decode('utf-8'))
    sub_obj = subprocess.Popen(
        from_client_cmd.decode('utf-8'),
        shell = True,
        stdout = subprocess.PIPE,
        stderr = subprocess.PIPE,
    )
    std_msg = sub_obj.stdout.read()
    std_msg_len = len(std_msg)
    print("指令的长度>>>",len(std_msg))
    msg_lenint_struct = struct.pack('i',std_msg_len)
    conn.send(msg_lenint_struct+std_msg)
服务端

进度条的打印

import time
for i in range(20):
    print('\r' + i*'*',end='')
    time.sleep(0.2)

  

posted @ 2019-02-24 15:03  等待の喵  阅读(...)  评论(...编辑  收藏