一:什么是粘包

  “粘包”, 即服务器端你调用时send 2次,但你send调用时,数据其实并没有立刻被发送给客户端,而是放到了系统的socket发送缓冲区里,等缓冲区满了、或者数据等待超时了,数据才会被send到客户端,这样就把好几次的小数据拼成一个大数据,统一发送到客户端了,这么做的目地是为了提高io利用效率,一次性发送总比连发好几次效率高嘛。 但也带来一个问题,就是“粘包”,即2次或多次的数据粘在了一起统一发送了。这里必须要想办法把粘包分开, 因为不分开,你就没办法取出来服务器端返回的命令执行结果的大小。

  1)time.sleep(0.5),经多次测试,让服务器程序sleep 至少0.5就会造成缓冲区超时。

  2)不用sleep,服务器端每发送一个数据给客户端,就立刻等待客户端进行回应,即调用 conn.recv(1024), 由于recv在接收不到数据时是阻塞的,这样就会造成,服务器端接收不到客户端的响应,就不会执行后面的conn.sendall(命令结果)的指令,收到客户端响应后,再发送命令结果时,缓冲区就已经被清空了,因为上一次的数据已经被强制发到客户端了。

#_*_coding:utf-8_*_

import socket
import os,subprocess server = socket.socket() #获得socket实例
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind(("localhost",9999)) #绑定ip port
server.listen() #开始监听 while True: #第一层loop
print("等待客户端的连接...")
conn,addr = server.accept() #接受并建立与客户端的连接,程序在此处开始阻塞,只到有客户端连接进来...
print("新连接:",addr )
while True: data = conn.recv(1024)
if not data:
print("客户端断开了...")
break #这里断开就会再次回到第一次外层的loop
print("收到命令:",data)
#res = os.popen(data.decode()).read() #py3 里socket发送的只有bytes,os.popen又只能接受str,所以要decode一下
res = subprocess.Popen(data,shell=True,stdout=subprocess.PIPE).stdout.read() #跟上面那条命令的效果是一样的
if len(res) == 0:
res = "cmd exec success,has not output!".encode("utf-8")
conn.send(str(len(res)).encode("utf-8")) #发送数据之前,先告诉客户端要发多少数据给它
print("等待客户ack应答...")
client_final_ack = conn.recv(1024) #等待客户端响应
print("客户应答:",client_final_ack.decode())
print(type(res))
conn.sendall(res) #发送端也有最大数据量限制,所以这里用sendall,相当于重复循环调用conn.send,直至数据发送完毕 server.close() 接收大数据 server端

  

#_*_coding:utf-8_*_

import socket
import sys client = socket.socket() client.connect(("localhost",9999)) while True:
msg = input(">>:").strip()
if len(msg) == 0:continue
client.send( msg.encode("utf-8") ) res_return_size = client.recv(1024) #接收这条命令执行结果的大小
print("getting cmd result , ", res_return_size)
total_rece_size = int(res_return_size)
print("total size:",res_return_size)
client.send("准备好接收了,发吧loser".encode("utf-8"))
received_size = 0 #已接收到的数据
cmd_res = b''
f = open("test_copy.html","wb")#把接收到的结果存下来,一会看看收到的数据 对不对
while received_size != total_rece_size: #代表还没收完
data = client.recv(1024)
received_size += len(data) #为什么不是直接1024,还判断len干嘛,注意,实际收到的data有可能比1024少
cmd_res += data
else:
print("数据收完了",received_size)
#print(cmd_res.decode())
f.write(cmd_res) #把接收到的结果存下来,一会看看收到的数据 对不对
#print(data.decode()) #命令执行结果 client.close() 接收大数据客户端

python网络编程-socket“粘包”(小数据发送问题)的更多相关文章

  1. UNIX网络编程——Socket粘包问题

    一.两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通讯连接,连接建立后不断开, 然后再进行报文发送和接收. 2.短连接 Client方与Server每进行一次报文收发交易 ...

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

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

  3. python网络编程之粘包

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

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

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

  5. python网络编程-socket编程

     一.服务端和客户端 BS架构 (腾讯通软件:server+client) CS架构 (web网站) C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发 二.OSI七层 ...

  6. Python网络编程socket

    网络编程之socket 看到本篇文章的题目是不是很疑惑,what is this?,不要着急,但是记住一说网络编程,你就想socket,socket是实现网络编程的工具,那么什么是socket,什么是 ...

  7. Python网络编程—socket(一)

    从今天开始python基础就介绍完毕了,下面我们将进阶到socket网络编程的介绍,那么socket是什么呢?我们带着这个问题开始今天的介绍: 一.socket初探 socket通常也称作" ...

  8. python --- 网络编程Socket

    网络编程 定义:所为网络编程即是对信息的发送和接收. 主要工作: (1)发送端:将信息以规定的协议组装成数据包. (2)接收端:对收到的数据包解析,以提取所需要的信息. Socket:两个在网络上的程 ...

  9. Learning-Python【29】:网络编程之粘包

    粘包问题 上一篇博客遗留了一个问题,在接收的最大字节数设置为 1024 时,当接收的结果大于1024,再执行下一条命令时还是会返回上一条命令未执行完成的结果.这就是粘包问题. 因为TCP协议又叫流式协 ...

随机推荐

  1. 【BZOJ3884】上帝与集合的正确用法

    Description 一句话题意,给定\(p\)作为模数: \(p\le 10^7\),数据组数\(T\le1000\). Solution 看到就弃疗了,再见...... 将模数\(p\)拆分成\ ...

  2. UOJ #126 【NOI2013】 快餐店

    题目链接:快餐店 震惊!某ZZ选手此题调了一天竟是因为……>>点击查看 一般碰到这种基环树的题都要先想想树上怎么做.这道题如果是在树上的话……好像求一遍直径就做完了?答案就是直径长度的一半 ...

  3. android与H5互相调用

    市面上很多android软件都有内嵌H5的,主要是为了节约成本,提高开发效率,其实现原理主要是通过Java代码和JavaScript代码的互相调用来实现. Java调用Js 1,webview初始化: ...

  4. 解题:WC 2006 水管局长

    题面 初见LCT,动态最小生成树+链上查询max,具体做法是把边转换成点(LCT只能维护点) 时光倒流,先把最后剩的连起来.然后查询就看链上最大值,修改看看链上最大值是否大于当前边,如果是就断开原来的 ...

  5. Hystrix的回退和zuul的回退总结

    1.Hystrix的回退: Ribbon: Feign: zuul的回退:

  6. 八、java常用类

    目录 一.字符串相关类 String类 StringBuffer类 二.基本数据类型包装类 三.Math类 四.File类 五.枚举类 一.字符串相关类 1.String类 java.lang.Str ...

  7. windows下静态编译pthread

    1. Building the library as a statically linkable library-------------------------------------------- ...

  8. 蓝桥杯 算法提高 学霸的迷宫 经典BFS问题

      算法提高 学霸的迷宫   时间限制:1.0s   内存限制:256.0MB      问题描述 学霸抢走了大家的作业,班长为了帮同学们找回作业,决定去找学霸决斗.但学霸为了不要别人打扰,住在一个城 ...

  9. 20155323 2016-2017-2 《Java程序设计》第7周学习总结

    20155323 2016-2017-2 <Java程序设计>第7周学习总结 使用Lambda语法来代替匿名的内部类,代码不仅简洁,而且还可读. 时间的度量:GMT.UT.TAI.UTC. ...

  10. 创建分区swap分区

    1.将文件系统卸载 #umount /sdc5 2.创建swap分区 #mkswap /dev/sdc5 3.激活swap分区 #swapon -a /dev/sdc5 4.查看swap分区情况 #s ...