二、解决黏包问题

2.1 解决黏包方法1

  • 计算消息实体的大小
  • 服务端接受两次,一次时消息大小,二次是消息实体,解决消息实体黏包
  • 客户端发送两次,一次是消息大小,一次是消息实体
  • 在两次收发之间加入一次多余通信,以防止消息大小和消息实体黏包

server端

import  socket

sk = socket.socket()

sk.bind(('127.0.0.1',9000))
sk.listen() conn,addr = sk.accept()
print(conn,addr)
while True:
cmd = input('请输入你的命令: ')
if cmd == 'q':
break conn.send(cmd.encode('gbk'))
data_length = conn.recv(1024).decode('gbk')
conn.send(b'ok') # 接受到消息大小后马上send,这样可以隔开两次recv,并且第二次接受指定长度的消息
data = conn.recv(int(data_length)).decode('gbk')
print(data) conn.close()
sk.close()

client

import  socket
import subprocess
sk = socket.socket() sk.connect(('127.0.0.1',9000)) while True:
cmd = sk.recv(1024).decode('gbk')
ret = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
std_out = ret.stdout.read()
std_err = ret.stderr.read() data_length = str(len(std_out)+len(std_err)).encode('gbk')
sk.send(data_length)
sk.recv(1024) # send消息大小后马上转入recv,隔开两次send。
sk.send(std_out)
sk.send(std_err) sk.close()

2.2  借助于struct模块

server端

import socket
import struct sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen() conn,addr = sk.accept() while True:
cmd = input('请输入命令: ')
conn.send(cmd.encode('utf-8'))
data_length_struct = conn.recv(4)
data_length = struct.unpack('i',data_length_struct)[0]
res = conn.recv(data_length).decode('gbk')
print(res) conn.close()
sk.close()

client端

import  socket
import subprocess
import struct sk = socket.socket()
sk.connect(('127.0.0.1',8080)) while True:
cmd = sk.recv(1024).decode('utf-8')
res = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout = res.stdout.read()
std_err = res.stderr.read()
data_length = len(stdout) + len(std_err)
data_length_struct = struct.pack('i',data_length)
sk.send(data_length_struct)
sk.send(stdout)
sk.send(std_err) sk.close()

2.3 通过struct定制报头传输大文件

server端

import socket
import struct
import json sk = socket.socket()
sk.bind(('127.0.0.1',8090))
sk.listen()
buffer = 2048 conn,addr = sk.accept() # 先接受报头
# 根据报头接受消息实体 struct_length = conn.recv(4) # 接受struct长度的包
bytes_head_length = struct.unpack('i',struct_length)[0] # 计算报头的长度
bytes_head = conn.recv(bytes_head_length) # 接受报头
json_head = bytes_head.decode('utf-8') # 将报头转换为str
head = json.loads(json_head) # 将报头转换为字典
fileSize = head['fileSize'] with open(head['fileName'],'wb') as f:
while fileSize:
if fileSize >= buffer:
content = conn.recv(buffer)
f.write(content)
fileSize -= buffer
else:
content = conn.recv(fileSize)
f.write(content)
break conn.close()
sk.close()

client端

import  socket
import os
import json
import struct sk = socket.socket()
sk.connect(('127.0.0.1',8090))
buffer = 2048
# 定制报头
# 先发送报头大小
# 发送报头
# 发送消息实体
head = {'fileSize':None,
'fileName':r'a.tar.gz',
'filePath':r'C:\Users\王诚\Desktop'}
file = os.path.join(head['filePath'],head['fileName'])
fileSize = os.path.getsize(file)
head['fileSize'] = fileSize
json_head = json.dumps(head) # 字典转换成了字符串
bytes_head = json_head.encode('utf-8') # 将字符串的head转换为bytes类型
bytes_head_length = len(bytes_head) # 计算bytes类型的head的大小 struct_length = struct.pack('i',bytes_head_length) # 通过struct转换为固定长度的bytes
sk.send(struct_length) # 先发报头的长度
sk.send(bytes_head) # 发报头
with open(file,'rb') as f:
while fileSize:
if fileSize >= buffer:
content= f.read(buffer)
sk.send(content)
fileSize -= buffer
else:
content = f.read(fileSize)
sk.send(content)
break sk.close()

三、检查客户端的合法性

使用hmac

server端

import  socket
import os
import hmac secret_key = b'wangys' sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen() def check_conn(conn):
msg = os.urandom(32)
conn.send(msg)
h = hmac.new(secret_key,msg)
server_msg = h.digest()
client_msg = conn.recv(1024)
res = hmac.compare_digest(server_msg,client_msg)
return res conn,addr = sk.accept()
res = check_conn(conn)
if res:
print('合法的客户端')
conn.close()
else:
print('不合法的客户端')
conn.close() sk.close()

client端

import socket
import hmac
secret_key = b'wangys' sk = socket.socket()
sk.connect(('127.0.0.1',8080)) msg = sk.recv(1024)
h = hmac.new(secret_key,msg)
client_msg = h.digest()
sk.send(client_msg) sk.close()

Python网络编程之黏包问题的更多相关文章

  1. Python学习笔记【第十四篇】:Python网络编程二黏包问题、socketserver、验证合法性

    TCP/IP网络通讯粘包问题 案例:模拟执行shell命令,服务器返回相应的类容.发送指令的客户端容错率暂无考虑,按照正确的指令发送即可. 服务端代码 # -*- coding: utf- -*- # ...

  2. 《Python》网络编程之黏包

    黏包 一.黏包现象 同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接收到之前执行的另外一部分结果,这种显现就是黏包. server端 import socket sk = s ...

  3. python socket编程和黏包问题

    一.基于TCP的socket tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端,有顺序,不重复,可靠.不会被加上数据边界. server端 import socket sk = so ...

  4. 网络编程- 解决黏包现象方案二之struct模块(七)

    上面利用struct模块与方案一比较,减少一次发送和接收请求,因为方案一无法知道client端发送内容的长度到底有多长需要和接收OK.多一次请求防止黏包,减少网络延迟

  5. Python网络编程,粘包、分包问题的解决

    tcp编程中的粘包.分包问题的解决: 参考:https://blog.csdn.net/yannanxiu/article/details/52096465 服务端: #!/bin/env pytho ...

  6. python网络编程-socket“粘包”(小数据发送问题)

    一:什么是粘包 “粘包”, 即服务器端你调用时send 2次,但你send调用时,数据其实并没有立刻被发送给客户端,而是放到了系统的socket发送缓冲区里,等缓冲区满了.或者数据等待超时了,数据才会 ...

  7. python网络编程之粘包

    一.什么是粘包 须知:只有TCP有粘包现象,UDP永远不会粘包 粘包不一定会发生 如果发生了:1.可能是在客户端已经粘了 2.客户端没有粘,可能是在服务端粘了 首先需要掌握一个socket收发消息的原 ...

  8. Python网络编程与并发编程

    网络编程基础 黏包 , 并发 计算机网络的发展及基础网络概念 Python 中的进程与 锁 Python IO 多路复用 \协程

  9. Python之路 - 网络编程之粘包

    Python之路 - 网络编程之粘包 粘包

随机推荐

  1. bat脚本基本命令和格式

    bat脚本 --莫非 BAT脚本与shell脚本区别 Shell脚本使用Linux/Unix下的命令,一般文件开头以#号来告诉系统这个脚本需要什么解释器来执行(如:#!/bin/bash采用bash而 ...

  2. Django_ORM操作 - 查询

    ORM 操作 必知必会13条 <1> all(): 查询所有结果 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 <3> get(* ...

  3. 【dp】求最长公共子序列

    [题目描述] 一个给定序列的子序列是在该序列中删去若干元素后得到的序列.确切地说,若给定序列X=<x1,x2,…,xm>X=<x1,x2,…,xm>,则另一序列Z=<z1 ...

  4. 快速找出网站中可能存在的XSS漏洞实践

    笔者写了一些XSS漏洞的挖掘过程记录下来,方便自己也方便他人. 一.背景 在本篇文章当中会一permeate生态测试系统为例,笔者此前写过一篇文章当中笔者已经讲解如何安装permeate渗透测试系统, ...

  5. gzy的摄影梦

    好像当身高180的摄影师啊. 记录一下素材,等自己有相机了,就一一实现. 竟然有人在看哎. 一袭红衣的女子,将手伸出窗外,开心的看这漫天大雪. 今天的晚霞,近处是蓝色,颜色逐渐变淡,一直延伸到远处.( ...

  6. Jira与Confluence集成、授权信息查看和问题汇总

    上一篇文章详细阐述了jira和confluence的安装部署和相关配置的操作记录,也介绍了两者之间其中一种集成方式:下面介绍另外的集成方式. 安装部署jira和confluence的顺序是,先安装ji ...

  7. 十行代码分清Java 的 || 和 &&

    发现有些同学到现在还没分不清 || 和 &&的作用 package System; /** * * @ClassName: RandomTest * @Description: 十行代 ...

  8. Java虚拟机内存溢出异常--《深入理解Java虚拟机》学习笔记及个人理解(三)

    Java虚拟机内存溢出异常--<深入理解Java虚拟机>学习笔记及个人理解(三) 书上P39 1. 堆内存溢出 不断地创建对象, 而且保证创建的这些对象不会被回收即可(让GC Root可达 ...

  9. 【转】Redis学习笔记(五)如何用Redis实现分布式锁(2)—— 集群版

    原文地址:http://bridgeforyou.cn/2018/09/02/Redis-Dsitributed-Lock-2/ 单机版实现的局限性 在上一篇文章中,我们讨论了Redis分布式锁的实现 ...

  10. 对于iOS架构的认识过程

    MVC 经典就是经典,没有之一.iOS中MVC架构,看懂斯坦福大学白胡子老头这张图基本上就可以了.   斯坦福大学MVC架构.png 简单理解,就是Controller对象拥有View和Model对象 ...