解决socket粘包的两种low版模式 os.popen()和struct模块
无注释版
os.popen()模式
server端
import socket
import os
phone = socket.socket()
phone.bind(("localhost",8088))
phone.listen()
while 1:
conn,addr = phone.accept()
while 1:
try:
from_client_data = conn.recv(1024)
if from_client_data.upper() == b'Q':
print("客户端退出")
break
print(from_client_data.decode('utf-8'))
cmd_res = os.popen(from_client_data.decode("utf-8")).read()
if len(cmd_res) == 0:
cmd_res = "cmd hs no output..."
print(len(cmd_res.encode('gbk')))
conn.send(str(len(cmd_res.encode('gbk'))).encode('gbk'))
client.ack = conn.recv(1024)
conn.send(cmd_res.encode('gbk'))
except ConnectionResetError:
break
conn.close()
phone.close()
client端
import socket
phone = socket.socket()
phone.connect(('localhost',8088))
while 1:
client_data = input(">>>")
if not client_data:
print("发送的内容不能为空")
continue
phone.send(client_data.encode("utf-8"))
if client_data.upper() == "Q":
quit()
else:
server_data = phone.recv(1024)
phone.send("准备好接收了".encode('utf-8'))
total_size = int(server_data.decode('gbk'))
total_data = b''
while 1:
if len(total_data) < total_size:
total_data += phone.recv(1024)
print(len(total_data))
else:
break
print(total_data.decode('gbk'))
phone.close()
struct模块解决粘包
server端
import socket
import subprocess
import struct
phone = socket.socket()
phone.bind(("localhost",8088))
phone.listen(5)
while 1:
conn,addr = phone.accept()
print(addr)
while 1:
try:
from_client_data = conn.recv(1024)
if from_client_data.upper() == b'Q':
print("客户端退出")
break
print(from_client_data.decode('utf-8'))
obj = subprocess.Popen(from_client_data.decode('utf-8'),
shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,)
ret = obj.stdout.read()+obj.stderr.read()
total_size = len(ret)
header = struct.pack('i',total_size)
print(total_size)
conn.send(header)
conn.send(ret)
except ConnectionResetError:
break
conn.close()
phone.close()
client端
import socket
import struct
phone = socket.socket()
phone.connect(('localhost',8088))
while 1:
client_data = input(">>>")
if not client_data:
print("发送的内容不能为空")
continue
phone.send(client_data.encode("utf-8"))
if client_data.upper() == "Q":
quit()
else:
server_data = phone.recv(4)
total_size = struct.unpack('i',server_data)[0]
total_data = b''
while 1:
if len(total_data) < total_size:
total_data += phone.recv(1024)
print(len(total_data))
else:
break
print(total_data.decode('gbk'))
# print(int(server_data.decode('gbk')))
phone.close()
有注释版
os.popen()模式
server端
import socket
import os
phone = socket.socket()
# 实例化一个socket对象
phone.bind(("localhost",8088))
# 绑定地址(host,port)到套接字,在AF_INET下,以元组(host,port)的形式表示地址
phone.listen(5)
# 开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
while 1: # 开启循环,多个用户同时连接(当然不是并发,排队连接)
conn,addr = phone.accept()
# 被动接受TCP客户端连接,(阻塞式)等待连接的到来,会有两个值,conn我也不明白是什么值,addr是客户端连接的地址
while 1: # 客户端与服务端多次对话,客户端多次执行循环
try: # 异常处理,客户端直接退出ConnectionResetError错误
from_client_data = conn.recv(1024) # 接收客户端数据
if from_client_data.upper() == b'Q':
# 判断客户端输入是否是q或Q,如果是q,直接退出当前连接
print("客户端退出")
break
print(from_client_data.decode('utf-8')) # 输出客户端转码后的数据
cmd_res = os.popen(from_client_data.decode("utf-8")).read() # 执行os命令,通过popen执行cmd命令
if len(cmd_res) == 0: # 如果没有该命令,返回下面结果
cmd_res = "cmd hs no output..."
conn.send(str(len(cmd_res.encode('gbk'))).encode('gbk')) # 发送数据,首先计算cmd_res的gbk字节长度,然后转换成字符串发送给客户端,因为int型不能发送
print(len(cmd_res.encode('gbk'))) # 输出该命令返回的长度
conn.send(cmd_res.encode('gbk')) # 执行一个接收,截断上下两个的粘包
conn.send(cmd_res.encode('gbk')) # 发送给客户端
except ConnectionResetError:
break
conn.close() # 关闭连接
phone.close() # 关闭连接
client端
import socket
phone = socket.socket() # 实例化对象
phone.connect(('localhost',8088)) # 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
while 1: # 循环输入
client_data = input(">>>")
if not client_data: # 如果输入为空,not client_data 则为True
print("发送的内容不能为空")
continue
phone.send(client_data.encode("utf-8")) # 给服务端发送信息
if client_data.upper() == "Q": # q退出
quit()
else:
server_data = phone.recv(1024) # 接收返回的字节长度
phone.send("准备好接收了".encode('utf-8')) # 给服务端发送消息,阻塞服务端上下造成粘包的问题(low版)
total_size = int(server_data.decode('gbk')) # 接收到的是字符串,转换成整型
total_data = b'' # 刚开始设置为0,空字符串则为0,前面加b表示字节
while 1: # 如果我收到的字节小于total_size,则一直循环
if len(total_data) < total_size:
total_data += phone.recv(1024) # 每次把信息加到total_data中
print(len(total_data))
else:
break
print(total_data.decode('gbk')) # 输出返回的结果
phone.close() # 关闭连接
struct模块解决粘包
server端
import socket
import subprocess
import struct
phone = socket.socket() # 实例化一个socket对象
phone.bind(("localhost",8088))
# 绑定地址(host,port)到套接字,在AF_INET下,以元组(host,port)的形式表示地址
phone.listen(5)
# 开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
while 1:# 开启循环,多个用户同时连接(当然不是并发,排队连接)
conn,addr = phone.accept()
# 被动接受TCP客户端连接,(阻塞式)等待连接的到来,会有两个值,conn我也不明白是什么值,addr是客户端连接的地址
print(addr)
while 1: # 客户端与服务端多次对话,客户端多次执行循环
try: # 异常处理,客户端直接退出ConnectionResetError错误
from_client_data = conn.recv(1024) # 接收客户端数据
if from_client_data.upper() == b'Q': # 判断客户端输入是否是q或Q,如果是q,直接退出当前连接
print("客户端退出")
break
print(from_client_data.decode('utf-8')) # 输出客户端转码后的数据
obj = subprocess.Popen(from_client_data.decode('utf-8'),
shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,)
# subprocess 模块中的代码
# shell: 命令解释器,相当于调用cmd 执行指定的命令。
# stdout:正确结果丢到管道中。
# stderr:错了丢到另一个管道中。
# windows操作系统的默认编码是gbk编码。
ret = obj.stdout.read()+obj.stderr.read() # 加的是字节
# 正确的输出跟错误的输出加起来,因为正确输出时,错误输出为空,所以加起来相当于0+1,没什么区别
total_size = len(ret) # 计算返回命令的长度
header = struct.pack('i',total_size) # 将一个数字转化成等长度的bytes类型。
print(total_size) # 打印出返回命令的长度
conn.send(header) # 发送固定长度的报头
conn.send(ret) # 给客户端发送返回命令的结果
except ConnectionResetError:
break
conn.close() # 关闭连接
phone.close() # 关闭连接
client端
import socket
import struct
phone = socket.socket() # 实例化对象
phone.connect(('localhost',8088)) # 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
while 1: # 循环输入
client_data = input(">>>")
if not client_data: # 如果输入为空,not client_data 则为True
print("发送的内容不能为空")
continue
phone.send(client_data.encode("utf-8")) # 给服务端发送信息
if client_data.upper() == "Q": # q退出
quit()
else:
server_data = phone.recv(4) # 接收报头长度
total_size = struct.unpack('i',server_data)[0] # 反解报头
total_data = b'' # 刚开始设置为0,空字符串则为0,前面加b表示字节
while 1: # 如果我收到的字节小于total_size,则一直循环
if len(total_data) < total_size:
total_data += phone.recv(1024) # 每次把信息加到total_data中
print(len(total_data))
else:
break
print(total_data.decode('gbk')) # 输出返回的结果,windows默认gbk
# print(int(server_data.decode('gbk')))
phone.close() # 关闭连接
解决socket粘包的两种low版模式 os.popen()和struct模块的更多相关文章
- 解决Socket粘包问题——C#代码
解决Socket粘包问题——C#代码 前天晚上,曾经的一个同事问我socket发送消息如果太频繁接收方就会有消息重叠,因为当时在外面,没有多加思考 第一反应还以为是多线程导致的数据不同步导致的,让他加 ...
- C#下利用封包、拆包原理解决Socket粘包、半包问题(新手篇)
介于网络上充斥着大量的含糊其辞的Socket初级教程,扰乱着新手的学习方向,我来扼要的教一下新手应该怎么合理的处理Socket这个玩意儿. 一般来说,教你C#下Socket编程的老师,很少会教你如何解 ...
- Socket粘包问题终极解决方案—Netty版(2W字)!
上一篇我们讲了<Socket粘包问题的3种解决方案>,但没想到评论区竟然炸了.介于大家的热情讨论,以及不同的反馈意见,本文就来做一个扩展和延伸,试图找到问题的最优解,以及消息通讯的最优解决 ...
- 网络编程基础【day09】:解决socket粘包之大数据(七)
本节内容 概述 linux下运行效果 sleep解决粘包 服务端插入交互解决粘包问题 一.概述 刚刚我们在window的操作系统上,很完美的解决了,大数据量的数据传输出现的问题,但是在Linux环境下 ...
- 解决tcp粘包问题
目录 什么是粘包(演示粘包现象) 解决粘包 实际应用 什么是粘包 首先只有tcp有粘包现象,udp没有粘包 socket收发消息的原理 发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地 ...
- python套接字解决tcp粘包问题
python套接字解决tcp粘包问题 目录 什么是粘包 演示粘包现象 解决粘包 实际应用 什么是粘包 首先只有tcp有粘包现象,udp没有粘包 socket收发消息的原理 发送端可以是一K一K地发送数 ...
- python网络编程基础之socket粘包现象
粘包现象两种 登陆 #服务端import json import socket server=socket.socket()#创建socket对象 ip_port=('127.0.0.1',8001) ...
- socket粘包现象加解决办法
socket粘包现象分析与解决方案 简单远程执行命令程序开发(内容回顾) res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=su ...
- Socket粘包问题的3种解决方案,最后一种最完美!
在 Java 语言中,传统的 Socket 编程分为两种实现方式,这两种实现方式也对应着两种不同的传输层协议:TCP 协议和 UDP 协议,但作为互联网中最常用的传输层协议 TCP,在使用时却会导致粘 ...
随机推荐
- 并发编程之美,带你深入理解java多线程原理
1.什么是多线程? 多线程是为了使得多个线程并行的工作以完成多项任务,以提高系统的效率.线程是在同一时间需要完成多项任务的时候被实现的. 2.了解多线程 了解多线程之前我们先搞清楚几个重要的概念! 如 ...
- 哈工大计算机网络Week1-网络应用
目录 哈工大计算机网络Week1-网络应用 2.1网络应用的体系结构 特点 应采取什么结构 C/S结构 客户机/服务器 P2P CS vs P2P 混合结构 思考题目 2.2网络应用的基本原理 网络应 ...
- Windows下必备的开发神器之Cmder使用说明
诚言,对于开发码字者,Mac和Linux果断要比Windows更贴心;但只要折腾下,Windows下也是有不少利器的.之前就有在Windows下效率必备软件一文中对此做了下记载:其虽没oh-my-zs ...
- Java开发IDEA插件推荐
IDEA插件推荐 Alibaba Java Coding Guidelines MyBatisCodeHelper-Pro Lombok GsonFormat AceJump Statistic Tr ...
- Linux系统-CENTOS7使用笔记
复制文件夹下的所有文件到另一个文件夹下 cp ~/dirname/* ~/otherdirname 解压rar文件 PS:在liunx下原本是不支持rar文件的,需要安装liunx下的winrar版本 ...
- @ImportResource导入的xml配置里的Bean能够使用@PropertySource导入的属性值吗?
每篇一句 大师都是偏执的,偏执才能产生力量,妥协是没有力量的.你对全世界妥协了你就是空气.所以若没有偏见,哪来的大师呢 相关阅读 [小家Spring]详解PropertyPlaceholderConf ...
- 五分钟部署一套完整的Zabbix
Zabbix-安装与使用 安装NTP yum install -y ntp 配置ntp.conf cd /etc/ vim ntp.conf # 打开之后讲一下内容添加 server cn.ntp.o ...
- 个人永久性免费-Excel催化剂功能第34波-提取中国身份证信息、农历日期转换相关功能
这两天又被刷朋友圈,又来了一个自主研发红芯浏览器,国产啊国产,这是谁的梦.就算国产了,自主了,无底线的夸大吹嘘无道德,企业如是,国家如是,大清已亡!再牛B的技术落在天天删敏感信息.无法治.无安全感可言 ...
- 下拉选择框,PopupWindow的使用
实现下拉选择框 直接上代码 Activity.java package com.example.shaofei.customerviewdemo1; import android.os.Bundle; ...
- 一文带你实现RPC框架
想要获取更多文章可以访问我的博客 - 代码无止境. 现在大部分的互联网公司都会采用微服务架构,但具体实现微服务架构的方式有所不同,主流上分为两种,一种是基于Http协议的远程调用,另外一种是基于RPC ...