socket模块

如果我们需要编写基于网络进行数据交互的程序 意味着我们需要自己通过代码来控制我们之前
所学习的OSI七层(很繁琐 很复杂 类似于我们自己编写操作系统)
socket类似于操作系统 封装了丑陋复杂的接口提供简单快捷的接口 socket 也叫套接字
基于文件类型的套件字家族(单机)
AF_UNIX
基于网络类型的套接字家族(联网)
AF_INET #python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET

代码展示

服务端展示:

import socket
service = socket.socket()
# 默认使用的是TCP协议 service.bind(('127.0.0.1',9999))
# 把地址绑定到套接字上,设定本地的地址,和一个端口号 service.listen(5)
# 最大同时监听连接数量 sock,addr = service.accept()
# 等待客户端传输数据 data = sock.recv(1024)
# 设置接受的最大消息字节 print(data.encode('utf8'))
# 打印接收到的消息 sock.send('回复客户端消息'.encode('utf8'))
# 给客户端发送消息 注意消息必须是bytes类型 sock.close()
# 关闭此次连接通道 server.close
# 关闭服务端服务 客户端展示: import socket client = socket.socket() client.connect(('127.0.0.1',9999))
# 通过服务端的地址 去连接服务端 client.send('客户端发送消息给服务端'.encode('utf8')) data = client.recv(1024)
# 接受服务端发送过来的消息 并设置最大字节
print(data.encode('utf8')) client.close()
# 断开于服务器的连接

黏包现象

1.在TCP协议下服务端连续执行3次接受消息,recv
2.客户端一次连续执行3次发送消息 send
服务端会一次性接收到客户端发的三次消息我们称这种问题为:'黏包现象' 黏包现在产生的原因
1.不知道每次接收的数据到底多大. soke.recv(1024) 这里出现问题导致
2.因为tcp协议是流式协议,数据就像流水一下,都会源源不绝的发送过来,没有间隔,所以导致会针对一些数据量小的,间隔时间短的信息误认为是同一条数据一起接收,或一起发送 如果解决黏包现象:核心 如何明确的知道接下来要接收的数据是多大,这样就能控制一次性接收多少数据,不会导致多收 # 如何将长度变化的数据全部完成制作成固定长度的数据

struct模块

import struct

msg = b'我是要发送的内容'
print(len(msg))
# 这样可以获取到待发送数据的真实长度
res = struct.pack('i',len(msg))
# 将数据打包成固定长度,打包模式'i'
print(len(res))
# 经过这样打包后的数据长度为 4 可以作为报头 real_len = struct.uppack('i',res)
# 这样可以解压打包,获取到真实数据的真实长度 msg = b'我是要发送的内容,即使我非常长 也是可以直接打包的哦'
res = struct.pack('i',len(msg))
print(len(res))
# 较长的数据打包后还是长度为 4 可以作为报头
real_lan = struct.uppick('i',res)
# 解包后还是会展示出真实长度的 '''
利用这个struct模块就可以生成出报头,
客户端:
1.将真实数据转换为bytes类型并计算长度
2.利用该模块,将真实长度制作成一个固定长度的报头 报头长度为4
3.将固定长度的报头先发送给服务端,服务端只需要在recv括号内填写固定长度的报头数字4
4.发完报头后再发送真实数据 服务端:
1.服务端发送消息前会先发送一个固定长度的报头
2.收到报头,利用struct模块反向解包获得真实数据长度
3.在用recv接收准确真实数据长度即可
''' 此方法可以暂时解决黏包问题,但是也有弊端
弊端:
1. struct模块无法打包数据量较大的数据,任何模式都不可以,大概可以打包的数据大小是 1字节- 8000字节左右
res = struct.packe('i',18888)
# 不建议打包相对较大的数据哦 2.报头是否可以传递更多信息,例如除了传递真实数据的大小,还有其他数据,电影名称 电影大小 电影简介等

struct模块正确用法

相对完美利用struct解决黏包问题的方法

设置一个字典,字典内可以包含多种信息,例如 :电影标题,电影文件大小,电影简介等 然后将字典左右报头 打包发送

data_dict = {'file_name':'倚天屠龙记',
'file_size': 2812819,
'file_desc': '一代经典,人人皆知'} 先利用 json 模块 把字典转换为bytes类型, data_json = json.dumps(data_dict)
res = struct.pack('i',data_json.encode('utf8')) '''
完美解决方案
客户端
1.制作一个真实数据的信息字典(数据长度,数据简介,数据名称)
2.然后把字典作为报头发送
3.发送字典数据
4.发送真实数据 服务端
1.接收固定长度的字典报头
2.解析出字典的真实长度并接收
3.通过字典获得真实数据的各项信息
4.接收真实数据长度 '''

处理黏包代码实战

import socket
import struct
import json 服务端: import json
import socket
import struct server = socket.socket()
# 1.创建一个TCP协议对象
server.bind(('192.168.1.99',8889))
# 2.服务端设定地址
server.listen(3)
# 3.设定半连接池等待接受最大人数
while True:
print('等待用户接入中....')
sock,addr = server.accept()
# 4.开启接收信息状态。sock=数据,addr = 对方 ip + 端口
print(f'用户:{addr[0]}已接入...')
while True:
data_dict_head = sock.recv(4)
# 接收报头 data_dict_len = struct.unpack('i',data_dict_head)[0]
# 获得报头字典真实长度
data_dict_bayes = sock.recv(data_dict_len)
# 接收真实字典 data_dict = json.loads(data_dict_bayes)
# 反序列化字典,拿到字典内容 total_size = data_dict.get('file_size') # 拿到真实数据长度
print(total_size)
with open(data_dict.get('file_name'),'wb')as f:
recv_size = 0
# 设置已接收字节数量
while recv_size < total_size:
# 循环接收数据,判断已接收字节是否和真实全部字节相同
data = sock.recv(2048)
# 一次最大接收2048字节
f.write(data)
recv_size += len(data)
print(f'文件:{data_dict.get("file_name")}接收完毕')
break 客户端: import socket
import struct
import os
import json client = socket.socket()
# 创建一个TCP协议对象
client.connect(('192.168.1.99', 8889))
# 连接一个服务端地址
file_size = os.path.getsize('/Users/moongod/Desktop/IMG_2368.MOV')
# 获取要传输文件的真实大小
print(file_size)
data_dict = {'file_name': 'IMG_2368.MOV', 'file_size': file_size,
'file_info': '设计文件'}
# 构建报头字典
data_dict_bytes = json.dumps(data_dict).encode('utf8')
# 打包报头字典
data_dict_len = struct.pack('i', len(data_dict_bytes))
client.send(data_dict_len)
# 发送字典报头
client.send(data_dict_bytes)
# 发送字典
with open('/Users/moongod/Desktop/IMG_2368.MOV', 'rb') as f:
for line in f:
client.send(line)
# 循环发送真实数据 '''
个人理解:
客户端: 1.制作字典报头 发字典报头 2.发真实字典 3.发真实数据 服务端: 1.收字典报头 解压出来字典字节长短
2.收真实字典数据, 解压出来 真实数据字节
3.收真实数据
'''

socket模块/TCP协议/黏包处理的更多相关文章

  1. python 全栈开发,Day35(TCP协议 粘包现象 和解决方案)

    一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...

  2. 铁乐学Python_Day34_Socket模块2和黏包现象

    铁乐学Python_Day34_Socket模块2和黏包现象 套接字 套接字是计算机网络数据结构,它体现了C/S结构中"通信端点"的概念. 在任何类型的通信开始之前,网络应用程序必 ...

  3. TCP协议粘包问题详解

    TCP协议粘包问题详解 前言 在本章节中,我们将探讨TCP协议基于流式传输的最大一个问题,即粘包问题.本章主要介绍TCP粘包的原理与其三种解决粘包的方案.并且还会介绍为什么UDP协议不会产生粘包. 基 ...

  4. tcp传输黏包

    tcp传输黏包 tcpip协议使用"流式"(套接字)进行数据的传输,就是说它保证数据的可达以及数据抵达的顺序,但并不保证数据是否在你接收的时候就到达,特别是为了提高效率,充分利用带 ...

  5. 网络编程协议(TCP和UDP协议,黏包问题)以及socketserver模块

    网络编程协议 1.osi七层模型 应用层  表示层  会话层  传输层  网络层  数据链路层  物理层 2.套接字 socket 有两类,一种基于文件类型,一种基于网络类型 3.Tcp和udp协议 ...

  6. 网路编程之socket与 socketserver、黏包

    socket与socketerver才是我们学习python中网络编程的重中之重在介绍他们两个之前我先介绍一些相关知识 一.socket 概念 咱们现在ois模型中找到socket所承担的角色 soc ...

  7. socket基于TCP(粘包现象和处理)

    目录 6socket套接字 7基于TCP协议的socket简单的网络通信 AF_UNIX AF_INET(应用最广泛的一个) 报错类型 单一 链接+循环通信 远程命令 9.tcp 实例:远程执行命令 ...

  8. socket使用TCP协议时,send、recv函数解析以及TCP连接关闭的问题

    Tcp协议本身是可靠的,并不等于应用程序用tcp发送数据就一定是可靠的.不管是否阻塞,send发送的大小,并不代表对端recv到多少的数据. 在阻塞模式下, send函数的过程是将应用程序请求发送的数 ...

  9. scoketserver模块(TCP协议 与 udp 协议)

    socketserver模块 ( 基于 TCP 协议 ) import socketserver # 自定义类用来处理通信循环 class MyTCPhanler(socketserver.BaseR ...

  10. 二、网络编程-socket之TCP协议开发客户端和服务端通信

    知识点:之前讲的udp协议传输数据是不安全的,不可靠不稳定的,tcp协议传输数据安全可靠,因为它们的通讯机制是不一样的.udp是用户数据报传输,也就是直接丢一个数据包给另外一个程序,就好比寄信给别人, ...

随机推荐

  1. 使用SkyWalking监控nginx (以openresty为例)

    安装使用SkyWalking先看这篇文章,地址:https://www.cnblogs.com/sanduzxcvbnm/p/15829781.html 使用SkyWalking监控nginx借助的是 ...

  2. Kubernetes角色访问控制RBAC和权限规则(Role+ClusterRole)

    文章转载自:https://blog.csdn.net/BigData_Mining/article/details/88849696 基于角色的访问控制(Role-Based Access Cont ...

  3. CentOS8本地安装Redash中文版,并且配置为生产环境

    Centos8内置的Python为3.6.8版本,以下是在内置Python3.6.8基础上的安装步骤.由于安装多版本Python会导致系统底层库需要下载源码重新编译,比较麻烦,不建议在多版本Pytho ...

  4. Java19虚拟线程都来了,我正在写的线程代码会被淘汰掉吗?

    Java19中引入了虚拟线程,虽然默认是关闭的,但是可以以Preview模式启用,这绝对是一个重大的更新,今天Java架构杂谈带大家开箱验货,看看这家伙实现了什么了不起的功能. 1 为什么需要虚拟线程 ...

  5. 20个超棒的jQuery bootstrap 插件

    1. Bootstrap File Input Bootstrap3.x 的一个增强版的HTML 5 文件选择控件,可以对图片文件和文本文件进行预览,以及其他功能.该插件增强了这些插件,并且将组件的初 ...

  6. TF-GNN踩坑记录(二)

    引言 最近在尝试构建GraphTensor时,尝试把默认的特征名hidden_state改成其他时,出现了奇怪的报错. 报错 WARNING:tensorflow:Gradients do not e ...

  7. ifram父页面、子页面元素及方法的获取调用

    page1 父页面 <div id="ifram" class="parent1"> <iframe frameborder="0& ...

  8. 路由组件构建方案(分库分表)V1

    路由组件构建方案V1 实现效果:通过注解实现数据分散到不同库不同表的操作. 实现主要以下几部分: 数据源的配置和加载 数据源的动态切换 切点设置以及数据拦截 数据的插入 涉及的知识点: 分库分表相关概 ...

  9. Java模拟生产者-消费者问题。生产者不断的往仓库中存放产品,消费者从仓库中消费产品。其中生产者和消费者都可以有若干个。在这里,生产者是一个线程,消费者是一个线程。仓库容量有限,只有库满时生产者不能存

    需求分析:生产者生产产品,存放在仓库里,消费者从仓库里消费产品. 程序分析: 1.生产者仅仅在仓储未满时候生产,仓满则停止生产. 2.消费者仅仅在仓储有产品时候才能消费,仓空则等待. 3.当消费者发现 ...

  10. Vscode设置标签页多行显示

    1.设置标签页多行展示的方法 文件–>首选项–>设置 2.勾选多行显示按钮 3.显示效果