【python开发】网络编程(下)

news2025/1/24 22:50:23

这里写目录标题

  • 一、OSI7
  • 二、TCP和UDP协议
    • (一)UDP和TCP示例代码
      • 1、UDP
      • 2、TCP
    • (二)TCP三次握手和四次挥手
  • 三、粘包
    • 1、实际案例1
    • 2、实际案例2
    • 3、实际案例3
  • 四、阻塞和非阻塞
  • 五、IO多路复用

一、OSI7

在电脑和电脑之间进行数据传输时,往往将数据包装为7层,分别为数据层、应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。

  1. 应用层:规定数据的格式;
  2. 表示层:对应用层数据的编码、压缩(解压)、分块、加密(解密)等任务;
  3. 会话层:负责与目标建立、中断链接;
  4. 传输层:建立端口到端口的通信,其实就是确定双方的端口信息;
  5. 网络层:标记目标IP信息;
  6. 数据链路层:对数据进行分组并设置源和目标mac地址。
  7. 物理层:将二进制数据在物理媒体上传输。
import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('110.242.68.3', 80)) #向服务端发送数据包

key = "你好"
#应用层,将数据打包为特定的格式
content = "GET /s?wd={} http1.1\r\nHost:www.baidu.com\r\n\r\n".format(key)
#表示层,对应用层数据的编码、压缩(解压)、分块、加密(解密)等任务
content = content.encode('utf-8')

client.sendall(content) #会话层,与膜表建立链接,同时也确定了双方的端口信息。标记目标IP的信息,设置源和目标电脑的MAC地址

result = client.recv(8196)
print(result.decode('utf-8'))

#会话层&传输层
client.close()

二、TCP和UDP协议

协议:规定 连接、收发数据的一些规定。

在OSI的 传输层 中,除了定义端口信息以外,常见的还可以指定UDP或TCP的协议,协议不同,链接和传输数据的细节会不同。

UDP(User Data Protocal)用户数据协议,是一个无连接的简单的面向数据包的传输层协议,客户端和服务端不需要提前建立连接,客户端可以直接向服务端发送数据即可。所以UDP是不可靠的,它只把应用程序传给IP层,但是不能保证他们能够到达目的地。由于不许需要提前在客户和服务器之间建立连接,所以没有超时重发的机制,所以传输速度较快。常见的有:语音通话、视频通话、实时游戏画面

TCP(Transcation Control Protocal)传输控制协议,是面向连接的协议,也就是说在收发数据之前,必须和对方建立可靠的连接,然后再收发数据,这种情况下会确保客户端收到服务端的信息,如果未收到“已经接受到”的信息,服务端会再次发送信息。常见的有:网站、手机app数据获取。

(一)UDP和TCP示例代码

1、UDP

服务端


import socket

socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind(('127.0.0.1', 8002))

while True:
    #没有accpet了
    data, (host, port) = socket.recvfrom(1024) #接收数据data,host代表IP地址,port为端口信息
    print(data, host, port)
    socket.sendto("好的".encode('utf-8'), (host, port))

客户端

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#不需要连接

while True:
    text = input("请输入要发送的内容:")
    if text.upper() == 'Q':
        break
    client.sendto(text.encode('utf-8'), ('127.0.0.1', 8002))
    data, (host, port) = client.recvfrom(1024)
    print(data.decode('utf-8'))

client.close()

2、TCP

服务端

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', 8001))
sock.listen(5)

while True:
    #2、等待,有人来连接就执行(阻塞)
    conn, addr = sock.accept()
    #3、等待,连接着发送信息(阻塞)
    client_data = conn.recv(1024)
    print(client_data)
    #4、给连接者回复信息
    conn.sendall(b'hello word')
    #5、关闭连接

sock.close()


客户端

import socket

#1、向指定IP发送连接申请
client = socket.socket()
client.connect(('127.0.0.1', 8001))

#2、连接成功后,发送信息
client.sendall(b"hello")

#3、等待,消息的回复(阻塞)
reply = client.recv(1024)
print(reply)

#4、关闭连接
client.close()

(二)TCP三次握手和四次挥手

网络中双方基于TCP进行通信,必须经过:
创建时,客户端和服务端进行三次握手

请添加图片描述
source prot是源端口,destination port是目标端口;sequence number是序列号,随机分配一个数字;acknowledgment number也是级分配的数值。

  1. 在创建连接时,客户端随机给出了一个序列号,seq=100;
  2. 当服务端收到信号时,给出seq=300,ack是在接收客户端seq100的基础上加1,最终ack=101;
  3. 当客户端接收到服务端的信号时,seq=101,ack实在服务端seq的基础上加1,ack=301。
  4. 在收发数据的过程中,只有有数据的传送就会应答(ack),如果没有ack,那么内部会尝试重复发送。

请添加图片描述
关闭连接时,客户端和服务端需要进行4次挥手:

请添加图片描述

三、粘包

当两台电脑进行收发数据时,其实不是直接将数据传输给对方。

  1. 对于发送者来说,执行sendall/send发送信息时,是将数据先发送给自己网卡的 写缓冲区,再由缓冲区将数据发送到对方网卡的 读缓冲区。
  2. 对于接收者来说,执行recv接收信息时,是从自己网卡的读缓冲区获取数据。

所以,如果发送者连续快速得发送两条信息,接收者在读取时会认为是一条信息,即:两个数据包粘在了一起。

#客户端
import socket


client = socket.socket()
client.connect(('127.0.0.1', 8001))

client.sendall('alex在吃'.encode('utf-8'))
client.sendall('翔'.encode('utf-8'))
client.close()



#服务端
import socket


sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', 8001))
sock.listen(5)


conn, addr = sock.accept()

client_data = sock.recv(1024)
print(client_data.decode('utf-8'))

conn.close()
sock.close()

如何解决粘包的问题?

每次发送信息时,都将信息划分为 头部(固定字节长度) 和 数据 两部分。例如:头部,用4个字节来表示后面的长度。

  1. 发送数据,先发送数据的长度,再发送数据(或拼接起来再发送)。
  2. 接收数据,先读4个字节就可以知道自己这个数据包中的数据长度,再根据长度读取数据。

头部需要一个数字并固定为4个字节,这个功能可以借助struct包来实现:

  1. struck把任意长度数字转化成具有固定4个字节长度的字节流;
  2. unpack把4个字节值恢复成原来的数字,返回最终的是元组。
import struct


v1 = struct.pack('i', 199)
# i => int 要转化的当前的数据是整型
print(v1) #b'\xc7\x00\x00\x00'


for item in v1:
    print(item, bin(item))

tup = struct.unpack("i", v1)
print(tup)  #(199,)
print(tup[0]) #199

解决黏包场景:
应用场景在实时通讯时,需要阅读此次发的消息是什么
不需要解决黏包场景:
下载或者上传文件的时候,最后要把包都结合在一起,黏包无所谓

1、实际案例1

客户端


import socket
import struct



client = socket.socket()
client.connect(("127.0.0.1", 9000))
# 处理收发数据的逻辑
strvar = input("请输入你要发送的数据")
mes = strvar.encode('utf-8')

length_ = len(mes)
print(length_)
#18
res = struct.pack("i", length_)

# 第一次发送的是字节流
client.sendall(res)
# 第二次发送的是真实的数据
client.sendall(mes)

message = '世界真美好'.encode('utf-8')
length1 = len(message)
res_ = struct.pack('i', length1)

client.sendall(res_)
client.sendall(message)

client.close()

服务端

import socket
import struct

sk = socket.socket()
sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sk.bind(("127.0.0.1", 9000))
sk.listen(5)

conn, addr = sk.accept()
header1 = sk.recv(4)
data_length1 = struct.unpack('i', header1)[0]
data1 = conn.recv(data_length1)
print(data1.decode('utf-8'))

header2 = sk.recv(4)
data_length2 = struct.unpack('i', header2)[0]
data2 = conn.recv(data_length2)
print(data2.decode('utf-8'))


2、实际案例2

客户端

import socket
import struct


client = socket.socket()
client.connect(('127.0.0.1', 8003))

data1 = "alex正在吃屎".encode('utf-8')
header1 = struct.pack('i', len(data1))
client.sendall(header1)
client.sendall(data1)

data2 = "翔".encode('utf-8')
header2 = struct.pack('i', len(data2))
client.sendall(header2)
client.sendall(data2)

client.close()

服务端


import socket
import struct


sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', 8003))
sock.listen(5)
conn, addr = sock.accept()

header1 = conn.recv(4)
data_length1 = struct.unpack('i', header1)[0]
data1 = conn.recv(data_length1)
print(data1.decode('utf-8'))

header2 = conn.recv(4)
data_length2 = struct.unpack('i', header2)[0]
data2 = conn.recv(data_length2)
print(data2.decode('utf-8'))


conn.close()
sock.close()

3、实际案例3

四、阻塞和非阻塞

五、IO多路复用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1495115.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Three.js--》探寻Cannon.js构建震撼的3D物理交互体验(二)

我们用three.js可以绘制出各种酷炫的画面,但是当我们想要一个更加真实的物理效果的话,这个时候我们就需要一个物理的库,接下来我们就讲解一下今天要学习的canon,它可以给我们提供一个更加真实的物理效果,像物体的张力、…

【center-loss 中心损失函数】 原理及程序解释(完)

文章目录 前言问题引出open-set问题抛出 解决方法softmax函数、softmax-loss函数解决代码(center_loss.py)原理程序解释 代码运用 如何梯度更新首先了解一下基本的梯度下降算法然后代码解释见下面train() 补充:外围知识(models.py…

同步通信和异步通信(RabbitMq学习前篇)

MQ学习前篇 文章目录 MQ学习前篇1、同步和异步通讯1.1、同步通讯和异步通讯1.2、同步调用存在的问题1.3、异步调用方案1.4、异步通信的缺点 1、同步和异步通讯 学习mq之前,就要先知道同步通讯和异步通讯的区别。 1.1、同步通讯和异步通讯 同步通讯就像是打电话&am…

部署LVS集群之DR模式

直接路由模式----DR模式 理念: 直接路由(是lvs的默认模式) DR模式和隧道模式唯一的区别:dr模式这四台服务器在同一网段,隧道模式 :这四台服务器不在同一网段 客户端 ------->代理服务器------->真实…

Unity中关于继承ScriptableObject的类

在游戏中我们会经常看到一些.asset的配置文件,而这些文件就是用一个自定义的类去继承ScriptableObject来生成的。比如当前有一些零散特效需要预加载,这个时候我们可以声明一个类去保存这些零散特效对象的信息,然后统一读取加载。 代码&#…

Pycharm与Anaconda安装

网址: Pycharm:https://www.jetbrains.com/pycharm/ Anaconda:https://www.anaconda.com/download/ 官网下载速度太慢可以选择到清华源下载:https://repo.anaconda.com/archive/ 一:Anaconda安装 安装: …

万丈高树平地起:通过中序与后序遍历数组构建二叉树

题目 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7], postorder [9,15,7,20,3] 输出&#xf…

机器学习---数据分割

之前的文章中写过,我们可以通过实验测试来对学习器的泛化误差进行评估并进而做出选择。 为此,需使用一个“测试集"(testing set)来测试学习器对新样本的判别能力,然后以测试集上的“测 试误差”(testing error)作为泛化误差的近似。通…

即插即用篇 | YOLOv8 引入 NAM 注意力机制 | 《NAM: Normalization-based Attention Module》

论文名称:《NAM: Normalization-based Attention Module》 论文地址:https://arxiv.org/pdf/2111.12419.pdf 代码地址:https://github.com/Christian-lyc/NAM 文章目录 1 原理2 源代码3 添加方式4 模型 yaml 文件template-backbone.yamltemplate-small.yamltemplate-large…

b站小土堆pytorch学习记录——P8-P9 Tensorboard的使用

文章目录 一、前置知识1.Tensorboard是什么2.SummaryWriter3.add_scalar()4.add_image() 二、代码1.一次函数2.蚂蚁和蜜蜂图片 一、前置知识 1.Tensorboard是什么 TensorBoard 是 TensorFlow 的可视化工具,它允许开发者可视化模型的图(graph&#xff0…

Nano 33 BLE Sense Rev2学习第二节——手机蓝牙接收数据

Nano 33 BLE Sense Rev2需要下载的程序 #include <ArduinoBLE.h> #include "Arduino_BMI270_BMM150.h"float x, y, z; int degreesX 0; int degreesY 0;BLEService ledService("19B10010-E8F2-537E-4F6C-D104768A1214"); // create service// cre…

论文阅读:Dataset Quantization

摘要 最先进的深度神经网络使用大量&#xff08;百万甚至数十亿&#xff09;数据进行训练。昂贵的计算和内存成本使得在有限的硬件资源上训练它们变得困难&#xff0c;特别是对于最近流行的大型语言模型 (LLM) 和计算机视觉模型 (CV)。因此最近流行的数据集蒸馏方法得到发展&a…

如何构建用于物体和标志检测的自定义模型

让我们快速了解一下AWS的机器学习技术栈&#xff0c;它几乎提供了解决我们业务问题所需的所有机器学习方面的支持。 物体检测是什么&#xff1f; 物体检测是从图像或视频帧中检测特定类别实例的任务。我们的目标是在图像/视频帧中找出哪里有什么物体。它是其他依赖物体的任务…

Locust中wait_time中匿名函数使用方法浅析

前言 翻出之前做个压测项&#xff0c;看到locust中对等待时间的实现方式感到好奇&#xff0c;于是总结下来。 源代码实现 def between(min_wait, max_wait):"""Returns a function that will return a random number between min_wait and max_wait.Example:…

数据库:2024/3/6

作业1&#xff1a;使用C语言完成数据库的增删改 代码&#xff1a; #include <myhead.h>//定义添加员工信息函数 int Add_worker(sqlite3 *ppDb) {//准备sql语句printf("请输入要添加的员工信息:\n");//从终端获取员工信息char rbuf[128]"";fgets(r…

centos7安装maven离线安装

1、从官方网站下载maven文件包 官方下载网站&#xff1a;https://maven.apache.org/download.cgi 2、创建文件夹解压文件 将下载好的安装包&#xff0c;放到创建的目录下&#xff0c;并解压 a、创建/app/maven文件 mkdir /app/mavenb、解压文件 tar -zxvf apache-maven-…

AIOps常见问题

AIOps的自动化通常指什么&#xff1f; AIOps 平台的自动化一般包括以下几个方面&#xff1a; 数据收集和整合&#xff1a;AIOps 平台可以从多个 IT 基础架构组件、应用需求与性能监视工具以及服务工单系统等数据源中收集并整合运维数据&#xff0c;形成一个全面的数据平台。数…

FC-AE-1553 协议

FC-AE-1553 协议 MIL-STD-1553B总线协议总线结构字格式消息传输方式 FC协议FC协议栈拓扑结构服务类型帧/序列/交换FC帧格式 FC-AE-1553网络构成帧类型命令帧状态帧数据帧 Information UnitsNC1NC2NC3-4NC5-7NT1-7 传输模式1. NC-NT2. NT-NC3. NT-NT4. 无数据字的模式命令5. 带数…

C++ spfa判断负环

给定一个 n 个点 m 条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c; 边权可能为负数。 请你判断图中是否存在负权回路。 输入格式 第一行包含整数 n 和 m 。 接下来 m 行每行包含三个整数 x,y,z &#xff0c;表示存在一条从点 x 到点 y 的有向边&#xff0c;边…

GEE 依照范围裁剪 下载Sentinel-2数据

0. GEE介绍 Google Earth Engine&#xff08;GEE&#xff09; 是由Google开发的一种云端平台&#xff0c;旨在提供强大的地理空间数据处理和分析工具。GEE集成了大量的遥感影像数据和地理空间数据集&#xff0c;以及高性能的计算资源&#xff0c;使用户能够在云端高效地进行大规…