zoukankan      html  css  js  c++  java
  • Python--网络编程-----解决粘包问题-简单版

    一、服务端代码为:

     1 import socket
     2 import subprocess
     3 import struct
     4 
     5 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     6 # phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
     7 phone.bind(('127.0.0.1', 8081))  # 0-65535:0-1024给操作系统使用
     8 phone.listen(5)
     9 
    10 print('starting......')
    11 while True:  # 链接循环
    12     conn, client_addr = phone.accept()
    13     print(client_addr)
    14 
    15     while True:  # 通信循环
    16         try:
    17             # 1、收命令
    18             cmd = conn.recv(1024)
    19             if not cmd:  # 适用于linux操作系统
    20                 break
    21             print('客户端的数据', cmd)
    22 
    23             # 2、执行命令,拿到结果
    24             obj = subprocess.Popen(cmd.decode('utf-8'), shell=True,
    25                                    stdout=subprocess.PIPE,
    26                                    stderr=subprocess.PIPE)
    27 
    28             stdout = obj.stdout.read()
    29             stderr = obj.stderr.read()
    30             # 3、把命令的结果返回给客户端
    31             # 第一步:制作固定长度的报头
    32             total_size = len(stdout) + len(stderr)
    33             header = struct.pack('i', total_size)
    34 
    35             # 第二步:把包头发送给客户端
    36             conn.send(header)
    37 
    38             # 第三步:再发送真实的数据
    39             conn.send(stdout)
    40             conn.send(stderr)
    41 
    42         except ConnectionResetError:  # 适用于Windows操作系统
    43             break
    44 
    45     conn.close()
    46 
    47 phone.close()

    二、客户端代码为:

     1 import socket
     2 import struct
     3 
     4 
     5 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     6 
     7 phone.connect(('127.0.0.1', 8081))
     8 
     9 while True:
    10     # 1、发命令
    11     cmd = input('>>:').strip()
    12     if not cmd:
    13         continue
    14     phone.send(cmd.encode('utf-8'))
    15 
    16     # 2、拿命令的结果,并打印
    17 
    18     # 第一步:先收报头
    19     header = phone.recv(4)
    20 
    21     # 第二步:从报头中解析出对真实数据的描述信息(数据的长度)
    22     total_size = struct.unpack('i', header)[0]
    23 
    24     # 第三步: 接收真实的数据
    25     recv_size = 0
    26     recv_data = b''
    27     while recv_size < total_size:
    28         res = phone.recv(1024)  # 1024是一个坑
    29         recv_data += res
    30         recv_size += len(res)
    31     print(recv_data.decode('gbk'))
    32 
    33 phone.close()

    在客户端依次输入,dir, ipconfig, dir,客户端结果为:

     1 >>:dir
     2  驱动器 C 中的卷是 OS
     3  卷的序列号是 7849-BAF9
     4 
     5  C:Usersxu516PycharmProjectsPython全栈开发第三模块网络编程5 解决粘包问题简单版 的目录
     6 
     7 2018/04/08  21:48    <DIR>          .
     8 2018/04/08  21:48    <DIR>          ..
     9 2018/04/08  21:40               128 struct模块的使用.py
    10 2018/04/08  21:48               802 客户端.py
    11 2018/04/08  21:48             1,487 服务端.py
    12                3 个文件          2,417 字节
    13                2 个目录 36,977,733,632 可用字节
    14 
    15 >>:ipconfig
    16 
    17 Windows IP 配置
    18 
    19 
    20 无线局域网适配器 本地连接* 3:
    21 
    22    媒体状态  . . . . . . . . . . . . : 媒体已断开连接
    23    连接特定的 DNS 后缀 . . . . . . . : 
    24 
    25 以太网适配器 VMware Network Adapter VMnet1:
    26 
    27    连接特定的 DNS 后缀 . . . . . . . : 
    28    本地链接 IPv6 地址. . . . . . . . : fe80::5d54:4c1:d7d6:c647%6
    29    IPv4 地址 . . . . . . . . . . . . : 192.168.189.1
    30    子网掩码  . . . . . . . . . . . . : 255.255.255.0
    31    默认网关. . . . . . . . . . . . . : 
    32 
    33 以太网适配器 VMware Network Adapter VMnet8:
    34 
    35    连接特定的 DNS 后缀 . . . . . . . : 
    36    本地链接 IPv6 地址. . . . . . . . : fe80::680e:7f79:aed1:fe62%10
    37    IPv4 地址 . . . . . . . . . . . . : 192.168.254.1
    38    子网掩码  . . . . . . . . . . . . : 255.255.255.0
    39    默认网关. . . . . . . . . . . . . : 
    40 
    41 无线局域网适配器 WLAN:
    42 
    43    连接特定的 DNS 后缀 . . . . . . . : DHCP HOST
    44    本地链接 IPv6 地址. . . . . . . . : fe80::9c84:419c:e3af:89dd%11
    45    IPv4 地址 . . . . . . . . . . . . : 192.168.0.106
    46    子网掩码  . . . . . . . . . . . . : 255.255.255.0
    47    默认网关. . . . . . . . . . . . . : 192.168.0.1
    48 
    49 以太网适配器 蓝牙网络连接:
    50 
    51    媒体状态  . . . . . . . . . . . . : 媒体已断开连接
    52    连接特定的 DNS 后缀 . . . . . . . : 
    53 
    54 隧道适配器 Teredo Tunneling Pseudo-Interface:
    55 
    56    连接特定的 DNS 后缀 . . . . . . . : 
    57    IPv6 地址 . . . . . . . . . . . . : 2001:0:9d38:953c:20d3:83ef:d86a:f024
    58    本地链接 IPv6 地址. . . . . . . . : fe80::20d3:83ef:d86a:f024%2
    59    默认网关. . . . . . . . . . . . . : ::
    60 
    61 >>:dir
    62  驱动器 C 中的卷是 OS
    63  卷的序列号是 7849-BAF9
    64 
    65  C:Usersxu516PycharmProjectsPython全栈开发第三模块网络编程5 解决粘包问题简单版 的目录
    66 
    67 2018/04/08  21:48    <DIR>          .
    68 2018/04/08  21:48    <DIR>          ..
    69 2018/04/08  21:40               128 struct模块的使用.py
    70 2018/04/08  21:48               802 客户端.py
    71 2018/04/08  21:48             1,487 服务端.py
    72                3 个文件          2,417 字节
    73                2 个目录 36,977,725,440 可用字节
    74 
    75 >>:

    从以上客户端输出结果可以看出,解决了粘包现象

  • 相关阅读:
    最终项目 XMessenger Servers
    Linux下patch的制作和应用
    谈移动互联网入口
    绑定服务后台播放音频的简单示例
    MOQL操作数(Operand) (三)
    浅析Hibernate映射(二)——关系映射(3)
    【Extjs优化二】 Form表单提交通用
    Delphi Dll(1)
    用Groovy思考 第三章 Groovy开发环境
    JUnit单元测试入门(三)--JUnit简单实例
  • 原文地址:https://www.cnblogs.com/xudachen/p/8747755.html
Copyright © 2011-2022 走看看