粘包产生的原因分析:

第一点:客户端向服务端发起命令请求,服务端接受命令请求,并返回对应的信息,如果信息过大,客户端一次接受不了,那么下一次请求依然返回

上一个命令的内容,就出现了粘包的情况。

第二点:发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)

所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样做,虽然节省了时间,但是发出的包却粘在了一起,造成粘包现象。

简单点的报头(有注释)

from socket import *  # socket里面很多功能用得到,属于特殊情况
import subprocess
import struct server=socket(AF_INET,SOCK_STREAM) # 生成套接字,绑定ip_port,服务端处于倾听状态
server.bind(('127.0.0.1',8080))
server.listen(5) while True:
conn,client_addr=server.accept() # 套接字和绑定的ip_port
print('新的客户端',client_addr) while True: # 下面的不循环结束不会进入下一个客户端
try:
cmd=conn.recv(1024) # cmd=b'dir' # 命令一般不会超过1024 不用管
if len(cmd) == 0:break # 运行系统命令 为什么不用system 因为system???
obj=subprocess.Popen(cmd.decode('utf-8'), # 字节解压成字符串
shell=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE
) stdout=obj.stdout.read()# 读出管道里数据 顺序不要乱 先stdout 然后stderr
stderr=obj.stderr.read() #1、先制作报头(固定长度)
total_size=len(stdout) + len(stderr) # 数据的总长度(整型)
header=struct.pack('i',total_size) # 把数据的长度按照i格式包装为固定的四个字节的报头 #2、先发送固定长度的报头
conn.send(header) # 为什么能解决粘包问题?因为把报头固定为四个字节,接受的时候固定接受 #3、再发送真实的数据
conn.send(stdout)
conn.send(stderr)
except ConnectionResetError:
break conn.close()

服务端

from socket import *
import struct client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080)) while True:
cmd=input('>>: ').strip()
if len(cmd) == 0:continue
client.send(cmd.encode('utf-8')) #1、先收固定长度的报头
header=client.recv(4) # 先接收固定长度的报头 #2、从报头中解析出对数据的描述信息
total_size=struct.unpack('i',header)[0] # 按照i格式解析出报头的数据信息,解析出来是一个元组(a,)形式,取第一个 #3、再收真实的数据
recv_size=0 # 应用层接受数据,初始数据为0
res=b''
while recv_size < total_size : # 接受数据小于传送过来的数据时,循环会一直进行下去
data=client.recv(1024)
res+=data
recv_size+=len(data) print(res.decode('gbk'))

客户端

复杂一点的报头(有注释)

from socket import *
import subprocess
import struct
import json server=socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5) while True:
conn,client_addr=server.accept()
print('新的客户端',client_addr) while True:
try:
cmd=conn.recv(1024) #cmd=b'dir'
if len(cmd) == 0:break # 运行系统命令
obj=subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE
) stdout=obj.stdout.read()
stderr=obj.stderr.read() #先制作报头
header_dic={ # 报头信息 包含文件名 文件大小 hash值
'filename':'a.txt',
'total_size':len(stdout) + len(stderr),
'hash':'xasf123213123'
}
header_json=json.dumps(header_dic) # 将包含报头信息的字典存成字符串格式
header_bytes=header_json.encode('utf-8') # 字符串编码成字节形式
print(header_json,type(header_json)) #1、先把报头的长度len(header_bytes)打包成4个bytes,然后发送
conn.send(struct.pack('i',len(header_bytes)))
#2、发送报头
conn.send(header_bytes)
#3、再发送真实的数据
conn.send(stdout)
conn.send(stderr)
except ConnectionResetError:
break conn.close()

服务端

from socket import *
import struct
import json client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080)) while True:
cmd=input('>>: ').strip()
if len(cmd) == 0:continue
client.send(cmd.encode('utf-8')) #1、先收4个字节,该4个字节中包含报头的长度
header_len=struct.unpack('i',client.recv(4))[0]
print(client.recv(4))
print(header_len) #2、再接收报头
header_bytes=client.recv(header_len) #从报头中解析出想要的内容
header_json=header_bytes.decode('utf-8')
header_dic=json.loads(header_json)
print(header_dic)
total_size=header_dic['total_size'] #3、再收真实的数据
recv_size=0
res=b''
while recv_size < total_size :
data=client.recv(1024)
res+=data
recv_size+=len(data) print(res.decode('gbk'))

客户端

模拟ssh的远程网络传输的更多相关文章

  1. ssh 中 远程文件传输

    scp 命令是 SSH 中最方便有用的命令了,试想,在两台服务器之间直接传送文件,仅仅用 scp 一个命令就完全解决了. 你可以在一台服务器上 以 root 身份运行 #scp servername: ...

  2. golang通过ssh实现远程文件传输

    使用ssh远程操作文件, 主要是创建ssh, 直接上代码 import ( "fmt" "github.com/pkg/sftp" "golang.o ...

  3. 网络编程 - 1.简单的套接字通信/2.加上通信循环/3.bug修复/4.加上链接循环/5.模拟ssh远程执行命令

    1.简单的套接字通信 服务端 ''' 服务端 接电话 客户端 打电话 1.先启动服务端 2.服务端有两种套接字 1.phone 用来干接收链接的 2.conn 用来干收发消息的 ''' import ...

  4. 网络编程之模拟ssh远程执行命令、粘包问题 、解决粘包问题

    目录 模拟ssh远程执行命令 服务端 客户端 粘包问题 什么是粘包 TCP发送数据的四种情况 粘包的两种情况 解决粘包问题 struct模块 解决粘包问题 服务端 客户端 模拟ssh远程执行命令 服务 ...

  5. [Python 网络编程] TCP、简单socket模拟ssh (一)

    OSI七层模型(Open System Interconnection,开放式系统互联) 应用层 网络进程访问应用层: 为应用程序进程(例如:电子邮件.文件传输和终端仿真)提供网络服务: 提供用户身份 ...

  6. 模拟ssh远程执行命令,粘包问题,基于socketserver实现并发的socket

    06.27自我总结 1.模拟ssh远程执行命令 利用套接字编来进行远程执行命令 服务端 from socket import * import subprocess server = socket(A ...

  7. Python 简单socket模拟ssh

    OSI七层模型(Open System Interconnection,开放式系统互联) 应用层 表示层 回话层 传输层 tcp,udp 网络层 ip,icmp 数据链路层 mac地址 物理层 物理网 ...

  8. Linux基础命令介绍七:网络传输与安全 wget curl rsync iptables

    本篇接着介绍网络相关命令:wget 文件下载工具.curl 网络数据传输工具.rsync 文件传输工具等. 本篇接着介绍网络相关命令 1.wget 文件下载工具 wget [option]... [U ...

  9. mac ssh,mac xshell,xshell替代,ssh客户端,ssh工具,远程桌面加速

    下载地址 Windows版下载地址:http://www.hostbuf.com/downloads/finalshell_install.exe Mac版,Linux版安装及教程:http://ww ...

随机推荐

  1. ios很好的开源库

    Tim9Liu9/TimLiu-iOS 自己总结的iOS.mac开源项目及库,持续更新.. 目录 UI 下拉刷新 模糊效果 AutoLayout 富文本 图表 表相关与Tabbar 隐藏与显示 HUD ...

  2. string interpolation in sql server

    https://sqlserver.dev129.com/2018/01/29/string-interpolation-in-t-sql/ Most programming languages ha ...

  3. YTU 2577: 小数计算——结构体

    2577: 小数计算--结构体 时间限制: 1 Sec  内存限制: 128 MB 提交: 978  解决: 647 题目描述 小数可以看成是一个点和两个数组成的,因此可以定义成一个小数的结构体,现在 ...

  4. vue开发购物车,解决全选单选问题

    实现全选单选,在vue中无法通过this获取input中的checkbox的checked属性,但是可以通过vue对input的特殊方式v-model来实现对应数据的绑定,同样也可以通过这种方式实现购 ...

  5. trying to draw too large(106,975,232 bytes) bitmap.

    Loading Large Bitmaps Efficiently This lesson teaches you to Read Bitmap Dimensions and Type Load a ...

  6. SPOJ:Free tour II (树分治+启发式合并)

    After the success of 2nd anniversary (take a look at problem FTOUR for more details), this 3rd year, ...

  7. Burpsuite实验一

    一.实验准备 win7系统 burpsuite 二.实验目的 进行重放攻击,观察结果 三.实验内容 本次实验并没有采取在虚拟机下进行,而是直接在win7系统中进行.首先配置一下环境,选择你常用的浏览器 ...

  8. GridFS大文件的添加、获取、查看、删除

    GridFS是一种在MongoDB中存储大二进制文件的机制,使用GridFS的原因有以下几种: 存储巨大的文件,比如视频.高清图片等. 利用GridFS可以简化需求. GridFS会直接利用已经建立的 ...

  9. MyBatis缓存设计

    和大多数ORM框架一样,为了尽可能减少数据库的访问,MyBatis设计支持缓存功能.设计上通过Cache接口提供SPI(服务提供接口),可以让第三方缓存提供具体的缓存实现,比如使用ehcache.Re ...

  10. VS2010中编写x64汇编的具体方法

    编写涉及系统特性的一些底层程序,特别是ShellCode,不可避免地要采用直接编写汇编代码的方式. 在目标平台为x86模式时,可以直接使用内联汇编,这个很多人都比较熟悉了,也非常地方便. 但是当目标平 ...