要解决粘包问题:
TCP:流式协议
特点:
1、数据流没有开头也没有结果,像水流一样
2、TCP协议有一个nagle算法,
nagle算法会将数据量较小,并且时间间隔较短的数据合成一条数据发送,
这么做可以减少网络IO次数,进而提升传输效率

1.struct模块

#1、把整型数字转成bytes类型
#2、转成的bytes是固定长度的 import struct
import json header_dic = {
'total_size': 31222222222121,
'md5': '123svsaef123sdfasdf',
'filename': 'a.txt'
} #序列化:内存中的数据结构----》转成一种中间格式(字符串)----》存到文件中
header_json=json.dumps(header_dic)
print(header_json,type(header_json)) #编码:编码后的结果为bytes类型
header_bytes=header_json.encode('utf-8')
header_size=len(header_bytes)
print(header_size) # #打包
obj=struct.pack('i',header_size)
print(obj,len(obj)) # b'Q\x00\x00\x00' 4 #解包
obj2=struct.unpack('i',obj)
print(obj2) # (81,)

打印结果:

{"total_size": 31222222222121, "md5": "123svsaef123sdfasdf", "filename": "a.txt"} <class 'str'>
81
b'Q\x00\x00\x00' 4
(81,)

result

2.通讯整个流程:

'''
流程:
服务端:制作报头,把报头信息丢到报头字典里,字典序列化得到json字符串,encode得到bytes
---->发报头长度(struct.pack打成4个bytes)--->发送报头---->发真实数据 客户端:先接收4个bytes:struct.unpack解包报头长度--->接收报头-->
解析报头:decode得到字符串,反序列化得到报头--->根据报头内的信息,收取真实的数据 '''

3.具体代码如下:

服务端:

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() #(连接对象,客户端的ip和端口) conn:tcp三次握手的一个产物,可以用来收发消息
print(client_addr) #此处client_addr的作用是可以知道哪个客户端建的链接,和通讯无关
while True:
try:
cmd=conn.recv(1024) #cmd为bytes类型,
obj=subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout=obj.stdout.read() #拿到系统执行的结果(subprocess执行的是window系统命令,解码需要gbk)
stderr=obj.stderr.read() # 1、制作报头
header_dic={
'total_size':len(stdout) + len(stderr),
'md5':'123svsaef123sdfasdf',
'filename':'a.txt'
}
header_json = json.dumps(header_dic) #json序列化报头
header_bytes = header_json.encode('utf-8') #字符串类型---->bytes类型,发送 # 2、先发送报头的长度
header_size=len(header_bytes)
conn.send(struct.pack('i',header_size)) # 3、发送报头
conn.send(header_bytes) # 4、发送真实的数据
conn.send(stdout) #send只能发bytes类型
conn.send(stderr)
except ConnectionResetError:
break
conn.close()
server.close()

客户端:

from socket import *
import struct
import json client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))
# print(client) while True:
cmd=input('>>>: ').strip()
if not cmd:continue
client.send(cmd.encode('utf-8')) #把命令结果发给服务器
#1、先收报头的长度根据报头内的信息,收取真实的数据
header_size=struct.unpack('i',client.recv(4))[0] #bytes类型,想拿到报头长度要对bytes进行解出 #2、接收报头
header_bytes=client.recv(header_size) #对应服务端的发送报头 #3、解析报头
header_json=header_bytes.decode('utf-8') #bytes类型---->字符串类型
header_dic=json.loads(header_json) #反序列化拿到报头
print(header_dic) total_size=header_dic[ 'total_size']
# print(total_size) #1025
#4、接收数据 recv_size=0
res=b''
while recv_size < total_size:
recv_data=client.recv(1024)
res+=recv_data
recv_size+=len(recv_data) print(res.decode('gbk'))
client.close()

基于tcp协议的套接字通信:远程执行命令的更多相关文章

  1. python 之 网络编程(基于TCP协议的套接字通信操作)

    第八章网络编程 8.1 基于TCP协议的套接字通信 服务端套接字函数 s.bind() 绑定(主机,端口号)到套接字 s.listen() 开始TCP监听 s.accept() 被动接受TCP客户的连 ...

  2. 什么是 socket?简述基于 tcp 协议的套接字通信流程?

    Socket的英文原义是"孔"或"插座".通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄, 可以用来实现不同虚拟机或不同计 ...

  3. 网络编程----socket介绍、基于tcp协议的套接字实现、基于udp协议的套接字实现

    一.客户端/服务器架构(C/S架构)                                                即C/S架构,包括: 1.硬件C/S架构(打印机) 2.软件C/S架 ...

  4. 网络编程(二)--TCP协议、基于tcp协议的套接字socket

    一.TCP协议(Transmission Control Protocol 传输控制协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会 ...

  5. 网络编程之TCP三次握手与四次挥手、基于TCP协议的套接字编程

    目录 TCP三次握手和四次挥手 背景描述 常用的熟知端口号 TCP概述 TCP连接的建立(三次握手) TCP四次挥手 如果已建立连接,客户端突然断开,会怎么办呢? 基于TCP协议的套接字编程 什么是S ...

  6. 网络编程(二)——TCP协议、基于tcp协议的套接字socket

    TCP协议与基于tcp协议的套接字socket 一.TCP协议(流式协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的 ...

  7. [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序]

    [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序] 为何学习socket套接字一定要先学习互联网协议: 1.首先:要想开发一款自己的C/S架构软件,就必须掌握socket ...

  8. python 之 网络编程(基于UDP协议的套接字通信)

    8.5 基于UDP协议的套接字通信 UDP协议:数据报协议 特点:无连接,一发对应一收,先启动哪一端都不会报错 优点:发送效率高,但有效传输的数据量最多为500bytes 缺点:不可靠:发送数据,无需 ...

  9. 基于TCP_socket套接字实现远程执行命令

    基于tcp的套接字实现远程执行命令的操作 ——客户端敲命令,服务端执行 #服务端 import socket import subprocess phone=socket.socket(socket. ...

随机推荐

  1. coding++:SpringBoot 处理前台字符串日期自动转换成后台date类型的三种办法

    第(1)种: 使用@DateTimeFormat(pattern = “yyyy-MM-dd HH:mm:ss”)注解在实体字段上. 这种方式的优点是:可以灵活的定义接收的类型 缺点很明显:不能全局统 ...

  2. Python实现压缩解压缩,移动复制copy文件

    import shutil import os from shutil import make_archive # 查看可压缩的文件类型 print(shutil.get_archive_format ...

  3. C#是什么?

    C# 是一个现代的.通用的.面向对象的编程语言,它是由微软(Microsoft)开发的,由 Ecma 和 ISO 核准认可的. C# 是由 Anders Hejlsberg 和他的团队在 .Net 框 ...

  4. 延时对象promise的使用

    promise是ES6(ECMA Script6)的新标准,只能在支持ES6的浏览器中使用 Promise是一个延时对象,创建延时对象时需要传入一个函数类型的参数 这个函数有两个参数:resolve和 ...

  5. ionic中select下拉框点击无反应解决办法

    两种解决办法: 1.在select外的div加入属性 data-tap-disabled=”true” 2.找到ionic.bundle.js文件 的下面这个函数,添加如图两行代码  

  6. 1.Metasploit介绍与基本命令

    Metasploit体系框架介绍 Metasploit是目前世界上领先的渗透测试工具,也是信息安全与渗透测试领域最大的开源项目之一.它彻底改变了我们执行安全测试的方式. Metasploit之所以流行 ...

  7. Blazor入门笔记(2)-分部类组件与组件的继承

    1.前言 本文接自Blazor的组件(1)-从0构建一个组件 2.分部类组件 Razor组件你可理解为就是一个类名与文件名相同的类,因此,可以新建一个同名的partial类,将组件中@code里面的代 ...

  8. 1050 String Subtraction (20分)

    Given two strings S​1​​ and S​2​​, S=S​1​​−S​2​​ is defined to be the remaining string after taking ...

  9. Springboot2(二)通过微信熟悉熟悉Spring-boot yml配置文件

    前言:Spring-boot的yml配置文件,这里就不在借助人.狗介绍了,试试套下微信! 创建yml文件 值得注意的是下图中有三种命名方法,前两种是对的,且第二种必须是横线而不是下划线! yml文件的 ...

  10. C语言 生日快乐

    #include <stdio.h> #include <math.h> #include <stdlib.h> #define I 20 #define R 34 ...