socket套接字及粘包问题
socket套接字
1、什么是socket
socket是一个模块,又称套接字,用来封装互联网协议(应用层以下的层)
2、为什么要有socket
实现应用层以下的层的工作,提高开发效率
3、怎么使用socket
先导入socket模块,先启动服务端套接字,再启动客户端套接字
# 服务端
import socket
# 买手机
server = socket.socket()
# 绑定手机号(IP,port)
# IP单机模式是127.0.0.1,局域网内使用cmd中ipconfig查询IPV4
# port设置8000以后的数据
server.bind(('127.0.0.1', 9876))
# 设置半连接池
server.listen(4)
# 可接收多个客户端数据连接,实现循环通信
while True:
# 接收客户端连接
conn, addr = server.accept()
# 查看对方地址
print(addr)
while True:
# 捕获异常机制
try:
# 接收客户端发来的数据,可一次接收1024bytes的数据
data = conn.recv(1024)
if len(date) == 0:
break
if data.decode('utf-8') == 'q':
break
print(data.decode('utf-8'))
# 向客户端发送消息
send_data = input('请输入向客户端发送的数据:')
conn.send(send_data.encode('utf-8'))
# 捕获异常,并打印出错误信息
except Exception as e:
print(e)
break
# 挂电话
conn.close()
# 客户端
import socket
# 买手机
client = socket.socket()
# 建立连接(IP,port)
client.connect(('127.0.0.1',9876))
while True:
try:
# 向对方发送数据
data = input('请输入向服务端发送的数据')
client.send((data.encode('utf--8')))
# 接收对方发来的数据可设置一次接收的bytes数,并打印
res_data = client.recv(1024)
if len(res_data) == 0:
break
if res_data.decode('utf-8') == 'q':
break
print(res_data.decode('utf-8'))
# 捕获异常,并打印出异常
except Exception as e:
print(e)
break
client.close()
粘包问题
问题1:
无法确认对方发送过来数据大小
问题2:
在发送数据间隔短并且数据量小的情况下,会将所有数据一次性发送
解决:需要确认对方发送的数据大小
# 客户端
# 问题1
import socket
client = socket.socket()
client.connect(('127.0.0.1', 9876))
while True:
try:
cmd = input('请输入向服务端发送的命令:')
client.send(cmd.encode('utf-8'))
# 接收服务端返回的数据
# 由于不知道会返回多少个bytes所以有问题1
date = client.recv(11910)
print(len(date))
print(date.decode('gbk'))
except Exception as e:
print(e)
break
client.close()
# 客户端
# 问题2
# 时间间隔短,并数据量小的情况下,会将所有的数据一次性发送,接收时不知道具体有几个
import socket
client = socket.socket()
client.connect(('127.0.0.1', 9876))
client.send(b'hello')
client.send(b'hello')
client.send(b'hello')
client.send(b'hello')
client.send(b'hello')
# 服务端
import socket
import subprocess
server = socket.socket()
server.bind(('127.0.0.1', 9876))
server.listen(4)
while True:
conn, addr = server.accept()
print(addr)
while True:
try:
# 接收客户端的数据,具体值不知道多大,所有有可能不能完全接收,有可能浪费资源
cmd = conn.recv(12)
if len(cmd) == 0:
break
cmd = cmd.decode('utf-8')
if cmd == 'q':
break
# 调用subprocess连接终端,对终端进行操作,并获取正确和错误的结果
obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# 拿到结果,并打印
result = obj.stdout.read() + obj.stderr.read()
print(result.decode('gbk'))
# 将结果返回给客户端
conn.send(result)
except Exception as e:
print(e)
break
conn.close()
解决粘包问题
使用struct模块
struct 是一个python内置的模块,它可以将固定长度的数据,打包成固定格式的长度
模式:i:4,或其他模式
作用:将真实数据做成一个固定长度的报头,发送给服务端,服务端接收报头,然后进行解包,获取真实数据的长度,进行接收数据即可
import struct
data = input('请输入传的数据').strip()
data = data.encode('utf-8')
# 制作报头,需要 i 的字符串和传入数据的长度
header = struct.pack('i',len(data))
print(header)
print(len(header))
# 解包( i 的字符串和报头)获取真实长度,得到一个元组,拿到元组第一个数就是真实长度
res = struct.unpack('i', header)[0]
print(res)
# utf-8中一个中文是3个bytes,一个英文是1个bytes
客户端:
1.先制作报头,并发送
2.发送真实数据
服务端:
1.接收报头,并且解包获取真实数据长度
2.根据真实数据长度,接收真实数据
# 客户端
import socket
import struct
client = socket.socket()
client.connect(('127.0.0.1', 9876))
while True:
try:
cmd = input('请输入向服务端发送的命令')
cmd_bytes = cmd.encode('utf-8')
# 做一个报头
header = struct.pack('i', len(cmd_bytes))
# 发送报头
client.send(header)
# 发送真实数据
client.send(cmd_bytes)
# 接受服务端返回的报头
reheader = client.recv(4)
# 解包
data_len = struct.unpack('i', reheader)[0]
result = client.recv(data_len)
print(result.decode('gbk'))
except Exception as e:
print(e)
break
client.close()
# 服务端
import socket
import subprocess
import struct
server = socket.socket()
server.bind(('127.0.0.1', 9876))
server.listen(5)
while True:
conn, addr = server.accept()
while True:
try:
# 获取报头
header = conn.recv(4)
# 获取真实数据长度
data_len = struct.unpack('i', header)[0]
# 准备接受真实数据
cmd = conn.recv(data_len)
cmd = cmd.decode('utf-8')
if cmd == 'q':
break
if len(cmd) == 0:
break
obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
result = obj.stdout.read() + obj.stderr.read()
print(len(result))
print(result.decode('gbk'))
# 将结果返回给客户端
header = struct.pack('i', len(result))
conn.send(header)
conn.send(result)
except Exception as e:
print(e)
break
conn.close()
# 客户端
import socket
import struct
import json
client = socket.socket()
client.connect(('127.0.0.1', 9876))
while True:
# 伪装电影数据
movie_name = input('请输入电影名称:')
movie_len = 10000101
send_dic = {
'movie_name': movie_name,
'movie_len': movie_len
}
# 序列化
json_data = json.dumps(send_dic)
# 制作报头
json_bytes = json_data.encode('utf-8')
header = struct.pack('i', len(json_bytes))
# 发送报头
client.send(header)
# 发送真实数据
client.send(json_bytes)
# 服务端
import socket
import json
import struct
server = socket.socket()
server.bind(('127.0.0.1', 9876))
server.listen(5)
while True:
conn, addr = server.accept()
print(addr)
while True:
try:
# 接收报头
header = conn.recv(4)
# 解包获取真实长度
json_len = struct.unpack('i', header)[0]
# 接收真实长度
json_bytes_data = conn.recv(json_len)
json_data = json_bytes_data.decode('utf-8')
# 反序列化得到数据
back_dic = json.loads(json_data)
print(back_dic)
except Exception as e:
print(e)
break
conn.close()
socket套接字及粘包问题的更多相关文章
- 网络编程——TCP协议、UDP协议、socket套接字、粘包问题以及解决方法
网络编程--TCP协议.UDP协议.socket套接字.粘包问题以及解决方法 TCP协议(流式协议) 当应用程序想通过TCP协议实现远程通信时,彼此之间必须先建立双向通信通道,基于该双向通道实现数 ...
- 网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法
TCP协议:传输协议,基于端口工作 三次握手,四次挥手 TCP协议建立双向通道. 三次握手, 建连接: 1:客户端向服务端发送建立连接的请求 2:服务端返回收到请求的信息给客户端,并且发送往客户端建立 ...
- 02网络编程( socket套接字+TCP粘包 )
目录 02 网络编程 一.socket套接字编程 二.简易代码模板 2.1 服务端 2.2 客户端 三.通信循环及代码优化 四.黏包现象 五.struct模块 六.简易版本报头 七.上传文件数据 * ...
- python开发socket套接字:粘包问题&udp套接字&socketserver
一,发生粘包 服务器端 from socket import * phone=socket(AF_INET,SOCK_STREAM) #套接字 phone.setsockopt(SOL_SOCKET, ...
- TCP Socket 套接字 和 粘包问题
一.Scoket 套接字 Scoket是应用层(应用程序)与TCP/IP协议通信的中间软件抽象层,它是一组接口.也可以理解为总共就三层:应用层,scoket抽象层,复杂的TCP/IP协议 基于TCP协 ...
- python基础--socket套接字、粘包问题
本地回环地址:127.0.0.1 简易版服务端: import socket server = socket.socket() # 就比如买了一个手机 server.bind(("127 ...
- day34 基于TCP和UDP的套接字方法 粘包问题 丢包问题
TCP 基于流的协议 又叫可靠性传输协议 通过三次握手 四次挥手 来保证数据传输完毕 缺点效率低 正因为是基于流的协议 所以会出现粘包问题粘包问题:原因一:是应为数据是先发送给操作系统,在操作系统中有 ...
- Day09: socket网络编程-OSI七层协议,tcp/udp套接字,tcp粘包问题,socketserver
今日内容:socket网络编程 1.OSI七层协议 2.基于tcp协议的套接字通信 3.模拟ssh远程执行命令 4.tcp的粘包问题及解决方案 5.基于udp协议的套接字 ...
- 基于UDP的套接字、粘包问题
一.基于UDP的套接字 UDP服务端 ss = socket() #创建一个服务器的套接字 ss.bind() #绑定服务器套接字 inf_loop: #服务器无限循环 cs = ss.recvfro ...
随机推荐
- Navicat Premium 12 安装与激活
一.Navicat Premium 12下载 官方下载地址:https://www.navicat.com.cn/download/navicat-premium 百度云盘:https://pan.b ...
- [转帖]Linux监测某一时刻对外的IP连接情况
Linux监测某一时刻对外的IP连接情况 https://blog.csdn.net/twt326/article/details/81454171 公司机器有病毒 需要分析一下. 之前有需要,在CS ...
- CMake方式编译
[1]CMake基础 CMake是一种跨平台编译工具 CMake主要是编写CMakeLists.txt文件 通过CMake命令将CMakeLists.txt文件转化为make所需的Makefile文件 ...
- mysql获取日期语句汇总
汇总一些MySQL获取日期的SQL语句. -- 今天 SELECT DATE_FORMAT(NOW(),'%Y-%m-%d 00:00:00') AS '今天开始'; SELECT DATE_FORM ...
- pod的yaml说明
apiVersion: v1 #指定api版本,此值必须在kubectl apiversion中 kind: Pod #指定创建资源的角色/类型 metadata: #资源的元数据/属性 name: ...
- KVM学习
获取镜像目前大小 # qemu-img info debian.img 添加额外的10G空间到镜像中 # qemu-img resize -f raw debian.img +10GB 注意:并不是所 ...
- Python 3 的 int 类型详解(为什么 int 不存在溢出问题?)
在以前的Python2中,整型分为int和long,也就是整型和长整型, 长整型不存在溢出问题, 即可以存放任意大小的数值,理论支持无限大数字. 因此在Python3 中,统一使用长整型,用int表示 ...
- 官方elasticsearch-certutiledit命令
地址:https://www.elastic.co/guide/en/elasticsearch/reference/7.5/certutil.html 语法: bin/elasticsearch-c ...
- 15、VUEX-Store
1.什么是VUEX Vuex是管理vue的组件状态的工具. 个人理解:vuex是管理组件之间通信的一个插件. 2.为什么要用VUEX 我们知道组件之间是独立的,组件之间想要实现通信,我目前知道的就只有 ...
- web api与mvc的区别
MVC主要用来构建网站,既关心数据也关心页面展示,而Web API只关注数据 Web API支持格式协商,客户端可以通过Accept header通知服务器期望的格式 Web API支持Self Ho ...