要解决粘包问题:
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. Redis调用lua生成验证码

    场景: ​ 通过微信公众号拿验证码在APP上绑定,为了防止重复,尝试使用reids-lua的方法实现此功能 以下是 php 调用 redis.eval 方法传入的 lua 方法,当然这只是修改后的,保 ...

  2. iOS 项目优化

    前言 iOS性能优化系列篇之"优化总体原则" 不要提前过度优化 要找到性能瓶颈 要在不同性能指标间权衡 要理解优化任务的底层运行机制 要有技术保障体系 一.启动速度优化 1.1 学 ...

  3. Cygwin工具编译Ardupilot方法

    注意:该编译方法生成的固件基于Chibios系统,如果想要Nuttx系统固件,需采用make编译,步骤见make编译说明部分. 软件安装准备 安装Cygwin 打开链接www.cygwin.com/i ...

  4. k8s 集群管理和微服务 适合做啥

    k8s 集群管理和微服务 适合做啥 都知道k8s是集群 适合微服务 有很多教程 但你可以先了解他能干啥 traefix 是负载均衡工具 k8s 适合部署无状态依赖的微服务 可以按需求开启多个微服务 管 ...

  5. iOS开发 - 开发版+企业版无线发布一键打包

    背景:项目进入快速迭代期,需要快速地交付出AdHoc版本和企业无线发布版本.每次打包都要来回切换bundle identifier和code signing,浪费很多时间. 示例项目名称名称为Test ...

  6. STM32F103ZET6通用定时器

    1.通用定时器简介 通用定时器是由一个可编程预分频器驱动的16位自动装载计数器构成.通用定时器可以应用于多种场合,如测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM).使用通用定时 ...

  7. Golang入门(3):一天学完GO的进阶语法

    摘要 在上一篇文章中,我们聊了聊Golang中的一些基础的语法,如变量的定义.条件语句.循环语句等等.他们和其他语言很相似,我们只需要看一看它们之间的区别,就差不多可以掌握了,所以作者称它们为&quo ...

  8. (js描述的)数据结构[字典](7)

    (js描述的)数据结构[字典](7) 一.字典的特点 1.字典的主要特点是一一对应关系. 2.使用字典,剋通过key取出对应的value值. 3.字典中的key是不允许重复的,而value值是可以重复 ...

  9. Qt开发环境搭建 - Windows + VS2010 + VS插件

    Qt 开发环境搭建 - Windows+VS2010+VS插件 1.Qt在Windows平台下的三种开发环境 方案 编辑器 编译器 调试器 一 Qt Creator MinGW GDB 二 Qt Cr ...

  10. DIV+CSS 样式简单布局Tab 切换

    <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> &l ...