博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python------网络编程2
阅读量:4697 次
发布时间:2019-06-09

本文共 3686 字,大约阅读时间需要 12 分钟。

  1. 黏包现象.

    • 系统缓冲区:用户或服务端接收信息与传输介质之间的媒介。
    • 缓冲区的作用:防止网络出现短暂的异常或波动而对计算机传输数据带来的直接影响。
      • Remark:缓冲区解决了上传下载的传输效率的问题,带来了黏包问题。
  2. 系统缓冲区.

    缓冲区的作用?

    没有缓冲区:如果你的网络出现短暂的异常或者波动,接收数据就会出现短暂的中断,影响你的下载或者上传的效率.

    但是 凡是都是双刃剑,缓冲区解决了上传下载的传输效率的问题,带来了黏包问题.

  3. 什么情况下产生黏包

    1. recv会产生黏包(如果recv接受的数据量(1024)小于发送的数据量,第一次只能接收规定的数据量1024,第二次接收剩余的数据量)
    2. send 也可能发生粘包现象.(连续send少量的数据发到输出缓冲区,由于缓冲区的机制,也可能在缓冲区中不断积压,多次写入的数据被一次性发送到网络)
  4. 解决黏包的方案

low版

server

import socketimport subprocessimport structphone = socket.socket()phone.bind(('127.0.0.1', 8888))phone.listen(5)# 4. 接收连接print('start')conn, addr = phone.accept()while 1:    try:        cmd = conn.recv(1024)        obj = subprocess.Popen(cmd.decode('utf-8'),                               shell=True,                               stdout=subprocess.PIPE,                               stderr=subprocess.PIPE,                               )        result = obj.stdout.read() + obj.stderr.read()        # print(f'服务端发送的总字节数{len(result)}')        # 1. 制作报头        total_size = len(result)        # 2. 将不固定长度的int类型的报头,转化成固定长度bytes 4个字节        # 将一个数字转化成等长度的bytes类型。        total_size_bytes = struct.pack('i', total_size)        # 3. 发送报头        conn.send(total_size_bytes)        # 4. 发送原数据        conn.send(result)    except ConnectionResetError:        breakconn.close()phone.close()

client

import socketimport structphone = socket.socket()phone.connect(('127.0.0.1', 8888))# 发消息while 1:    cmd = input('>>>').strip()    phone.send(cmd.encode('utf-8'))    # 1. 接收报头    head_bytes = phone.recv(4)    # 2. 将报头反解回int类型    total_size = struct.unpack('i', head_bytes)[0]  # 1517    # 3. 循环接收原数据    total_data = b''    while len(total_data) < total_size:        total_data += phone.recv(1024)    print(total_data.decode('gbk'))# 关机phone.close()

旗舰版

server

import socketimport subprocessimport structimport jsonphone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)phone.bind(('127.0.0.1', 8878))phone.listen(5)while 1:    conn, client_addr = phone.accept()    print(client_addr)    while 1:        try:            cmd = conn.recv(1024)            ret = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)            correct_msg = ret.stdout.read()            error_msg = ret.stderr.read()            # 1 制作固定报头            total_size = len(correct_msg) + len(error_msg)            header_dict = {                'md5': 'fdsaf2143254f',                'file_name': 'f1.txt',                'total_size': total_size,            }            header_dict_json = json.dumps(header_dict)  # str            bytes_headers = header_dict_json.encode('utf-8')            header_size = len(bytes_headers)            header = struct.pack('i', header_size)            # 2 发送报头长度            conn.send(header)            # 3 发送报头            conn.send(bytes_headers)            # 4 发送真实数据:            conn.send(correct_msg)            conn.send(error_msg)        except ConnectionResetError:            breakconn.close()phone.close()

client

import socketimport structimport jsonphone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)phone.connect(('127.0.0.1', 8878))while 1:    cmd = input('>>>').strip()    if not cmd: continue    phone.send(cmd.encode('utf-8'))    # 1,接收固定报头    header_size = struct.unpack('i', phone.recv(4))[0]    # 2,解析报头长度    header_bytes = phone.recv(header_size)    header_dict = json.loads(header_bytes.decode('utf-8'))    # 3,收取报头    total_size = header_dict['total_size']    # 3,根据报头信息,接收真实数据    recv_size = 0    res = b''    while recv_size < total_size:        recv_data = phone.recv(1024)        res += recv_data        recv_size += len(recv_data)    print(res.decode('gbk'))phone.close()

转载于:https://www.cnblogs.com/hql1117/p/11201832.html

你可能感兴趣的文章
配置maven
查看>>
使用Xshell连接Ubuntu
查看>>
JAVA 仿 MS word 字数统计
查看>>
[2019HDU多校第五场][HDU 6626][C. geometric problem]
查看>>
OpenStack 镜像服务 Glance部署(七)
查看>>
STL源码解析-04序列容器-02list
查看>>
HDU 4865 Peter's Hobby(2014 多校联合第一场 E)(概率dp)
查看>>
设置ISE/vivado中默认文本编辑器为gvim
查看>>
Spring 基于注解的AOP实现
查看>>
AVAudioPlayer简易封装
查看>>
swappiness参数设置与内存交换
查看>>
修改es最大返回结果数
查看>>
Android实战技巧之六:PreferenceActivity使用详解
查看>>
SUSE12 网卡配置、SSH远程配置、解决CRT密钥交换失败,没有兼容的加密程序
查看>>
平台网盘
查看>>
原生ajax jq跨域
查看>>
在MySQL中操作日期和时间
查看>>
WebService&CXF
查看>>
hibernate框架环境搭建与使用
查看>>
不同大小的字体底部对齐
查看>>