Python 网络编程 -- WebSocket编程

news2025/6/6 13:02:16

作者主要是为了用python构建实时网络通信程序。

概念性的东西越简单越好理解,因此,下面我从晚上摘抄的概念 + 我的理解。

什么是网络通信?

更确切地说,网络通信是两台计算机上的两个进程之间的通信。比如,浏览器进程和新浪服务器上的某个Web服务进程在通信,而QQ进程是和腾讯的某个服务器上的某个进程在通信。

而网络编程就是针对网络通信的编程。

1.网络编程基础

1.1 基本概念与协议

TCP/IP协议栈

网络编程的基础是 理解数据在网络中的传输过程,这通常通过OSI模型和TCP/IP协议栈进行解释。而TCP/IP协议栈则是实际应用中更为广泛的模型,包含物理层、数据链路层、网络层、传输层、会话层、表示层和应用层

计算机为了联网,需要规定通信协议,一开始是不统一的,相互不同协议之间的计算机交互是困难的。因此,就出现了互联网协议簇,任何网络只要遵守这个协议,就可以连入互联网。

互联网协议,包括上百种协议,最重要的当属TCP/IP协议,因此,大家把互联网协议简称TCP/IP协议。

通信的时候,双方必须知道对方的标识,好比发邮件必须知道对方的邮件地址。互联网上每个计算机的唯一标识就是IP地址,类似123.123.123.123。如果一台计算机同时接入到两个或更多的网络,比如路由器,它就会有两个或多个IP地址,所以,IP地址对应的实际上是计算机的网络接口,通常是网卡。

IP协议负责把数据从一台计算机通过网络发送到另一台计算机。数据被分割成一小块一小块,然后通过IP包发送出去。由于互联网链路复杂,两台计算机之间经常有多条线路,因此,路由器就负责决定如何把一个IP包转发出去。IP包的特点是按块发送,途径多个路由,但不保证能到达,也不保证顺序到达。

TCP协议则是建立在IP协议之上的。TCP协议负责在两台计算机之间建立可靠连接,保证数据包按顺序到达。TCP协议会通过握手建立连接,然后,对每个IP包编号,确保对方按顺序收到,如果包丢掉了,就自动重发。

许多常用的更高级的协议都是建立在TCP协议基础上的,比如用于浏览器的HTTP协议、发送邮件的SMTP协议等。

一个TCP报文除了包含要传输的数据外,还包含源IP地址和目标IP地址,源端口和目标端口。

端口有什么作用?在两台计算机通信时,只发IP地址是不够的,因为同一台计算机上跑着多个网络程序。一个TCP报文来了之后,到底是交给浏览器还是QQ,就需要端口号来区分。每个网络程序都向操作系统申请唯一的端口号,这样,两个进程在两台计算机之间建立网络连接就需要各自的IP地址和各自的端口号。

一个进程也可能同时与多个计算机建立链接,因此它会申请很多端口。

TCP

TCP (Transmission Control Protocol) 是面向连接的、提供端到端可靠的数据流(flow of data)。TCP 提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。

“面向连接”就是在正式通信前必须要与对方建立起连接。这一过程与打电话很相似,先拨号振铃,等待对方摘机说“喂”,然后才说明是谁。

端到端的数据流,建立在IP协议之上,提供超时重发、重复数据校验、流量控制灯基本功能。

保证数据能从一端到另一端。

三次握手

TCP 是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个 TCP 连接必须要经过三次“握手”才能建立起来,简单的讲就是:

  1. 主机 A 向主机 B 发出连接请求数据包:“我想给你发数据,可以吗?”;
  2. 主机 B 向主机 A 发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你来吧”;
  3. 主机 A 再发出一个数据包确认主机 B 的要求同步:“好的,我来也,你接着吧!”

三次“握手”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机 A 才向主机 B 正式发送数据。

A和B要通过 TCP通信的流程:

A 连接B,B被连接允许A连接,A接受到响应确认连接B。 -> A和B可以通信了。

UDP

UDP (User Datagram Protocol) 面向无连接的,主机发送独立的数据报(datagram)给其他主机,不保证数据到达。由于 UDP 在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。

而无连接是一开始就发送信息(严格说来,这是没有开始、结束的),只是一次性的传递,是先不需要接受方的响应,因而在一定程度上也无法保证信息传递的可靠性了,就像写信一样,我们只是将信寄出去,却不能保证收信人一定可以收到。

通信时,可以不用与目标主机建立连接,就能发送数据。

A和B通信,直接发送就可以,不用管对方是否  "可连接"。

TCP 是面向连接的,有比较高的可靠性, 一些要求比较高的服务一般使用这个协议,如FTP、Telnet、SMTP、HTTP、POP3 等,而 UDP 是面向无连接的,使用这个协议的常见服务有 DNS、SNMP、QQ 等。对于 QQ 必须另外说明一下,QQ2003 以前是只使用UDP协议的,其服务器使用8000端口,侦听是否有信息传来,客户端使用 4000 端口,向外发送信息(这也就不难理解在一般的显IP的QQ版本中显示好友的IP地址信息中端口常为4000或其后续端口的原因了),即QQ程序既接受服务又提供服务,在以后的 QQ 版本中也支持使用 TCP 协议了。

端口

一般来说,一台计算机具有单个物理连接到网络。数据通过这个连接去往特定的计算机。然而,该数据可以被用于在计算机上运行的不同应用。那么,计算机知道哪个应用程序转发数据?通过使用端口。

在互联网上传输的数据是通过计算机的标识和端口来定位的。计算机的标识是 32-bit 的 IP 地址。端口由一个 16-bit 的数字。

在诸如面向连接的通信如 TCP,服务器应用将套接字绑定到一个特定端口号。这是向系统注册服务用来接受该端口的数据。然后,客户端可以在与服务器在服务器端口会合,如下图所示:

网络基础 - 图2

TCP 和 UDP 协议使用的端口来将接收到的数据映射到一个计算机上运行的进程。

在基于数据报的通信,如 UDP,数据报包中包含它的目的地的端口号,然后 UDP 将数据包路由到相应的应用程序,如本图所示的端口号:

网络基础 - 图3

端口号取值范围是从 0 到 65535 (16-bit 长度),其中范围从 0 到 1023 是受限的,它们是被知名的服务所保留使用,例如 HTTP (端口是 80)和 FTP (端口是20、21)等系统服务。这些端口被称为众所周知的端口(well-known ports)。您的应用程序不应该试图绑定到他们。

嗯 ...,网络通信具体来讲,是两个进程之间的通信,很显然我们只要目标主机的IP是没法跟对方通信的,因此我们还必须知道目标进程运行占用的端口,通过 ip + port来与其通信。

2. Socket

Socket(套接字):是在网络上运行两个程序之间的双向通信链路的一个端点socket绑定到一个端口号,使得 TCP 层可以标识数据最终要被发送到哪个应用程序

正常情况下,一台服务器在特定计算机上运行,​​并具有被绑定到特定端口号的 socket。服务器只是等待,并监听用于客户发起的连接请求的 socket 。

在客户端:客户端知道服务器所运行的主机名称以及服务器正在侦听的端口号。建立连接请求时,客户端尝试与主机服务器和端口会合。客户端也需要在连接中将自己绑定到本地端口以便于给服务器做识别。本地端口号通常是由系统分配的。

Socket - 图1

如果一切顺利的话,服务器接受连接。一旦接受,服务器获取绑定到相同的本地端口的新 socket ,并且还具有其远程端点设定为客户端的地址和端口。它需要一个新的socket,以便它可以继续监听原来用于客户端连接请求的 socket 。

Socket - 图2

在客户端,如果连接被接受,则成功地创建一个套接字和客户端可以使用该 socket 与服务器进行通信。

客户机和服务器现在可以通过 socket 写入或读取来交互了。

端点是IP地址和端口号的组合。每个 TCP 连接可以通过它的两个端点被唯一标识。这样,你的主机和服务器之间可以有多个连接。

Socket是对互联网通信协议(如TCP/IP)的封装和应用,它提供了一个调用接口(API),通过这个接口我们可以使用这些协议栈来与目标计算机进行通信。

在具体的编程语言中,针对不同的通信协议会有不同的Socket实现。当你需要与目标计算机进行基于某个协议的通信时,你可以调用相应协议的Socket实现。这些Socket实现会根据协议的要求进行数据的封装和解封装,以便你能够与目标计算机进行通信。

因此,通过创建针对特定协议的Socket实现,你就可以使用Socket进行基于该协议的通信了。

具体举一下例子:

如果抖音有一个通信协议,并且针对Java提供了一个具体的SDK,那么这个SDK中应该包含了一个Socket的实现,用于与抖音服务器进行通信。

当你创建这个Socket时,你可以使用SDK提供的API来与抖音服务器建立连接、发送和接收数据。SDK会根据抖音的通信协议对数据进行封装和解封装,以便你能够与抖音服务器进行通信。

因此,通过创建这个Socket,你就可以使用SDK提供的API与抖音服务器进行通信了。

服务器指一个管理资源并为用户提供服务的计算机软件,通常分为文件服务器、数据库服务器和应用程序服务器。严格来说,服务器本身就是计算机硬件,并在其中运行的管理软件的一种管理资源,就如同电脑。按硬件还会分塔式服务器、卡片机、小型机。是一个大的概念,任何一台电脑安装了软件的服务器端就可以叫服务器。

2.Python网络编程

Socket

python提供了内置socket库,从而能够进行网路通信。下面我们直接展示一个案例。

下面简单利用了sockert库,来建立一个服务器,并且建立了一个客户端,去访问服务器并进行数据交互。

来源于菜鸟编程: Python 网络编程 | 菜鸟教程 (runoob.com)

Server.py

import socket
if __name__ == '__main__':
    # 建立一个服务端
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(('localhost', 6999))  # 绑定要监听的端口
    server.listen(5)  # 开始监听 表示可以使用五个链接排队
    while True:  # conn就是客户端链接过来而在服务端为期生成的一个链接实例
        conn, addr = server.accept()  # 等待链接,多个链接的时候就会出现问题,其实返回了两个值
        print(conn, addr)
        while True:
            try:
                data = conn.recv(1024)  # 接收数据
                print('recive:', data.decode())  # 打印接收到的数据
                conn.send(data.upper())  # 然后再发送数据
            except ConnectionResetError as e:
                print('关闭了正在占线的链接!')
                break
        conn.close()

client.py

import socket
if __name__ == '__main__':
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 声明socket类型,同时生成链接对象
    client.connect(('localhost', 6999))  # 建立一个链接,连接到本地的6969端口
    while True:
        # addr = client.accept()
        # print '连接地址:', addr
        msg = '欢迎访问菜鸟教程!'  # strip默认取出字符串的头尾空格
        client.send(msg.encode('utf-8'))  # 发送一条信息 python3 只接收btye流
        data = client.recv(1024)  # 接收一个信息,并指定接收的大小 为1024字节
        print('recv:', data.decode())  # 输出我接收的信息
    client.close()  # 关闭这个链接

WebSocket

 PS:以下全引用于HTML 菜鸟编程: HTML5 WebSocket | 菜鸟教程 (runoob.com)

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。

当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

以下 API 用于创建 WebSocket 对象。

我们可以看出,websocket协议是基于tcp协议的全双工通信协议。

它,允许服务端主动向客户端推送数据。而且,只需要一次握手,就可建立一次长连接

与传统 AJAX轮训方法实现推送技术相比,发送请求的次数减少,(数据每一次更新,就代表一次ajax的请求和响应,这是相对比较浪费带宽资源的,通过websocket,客户端和服务端可以建立一次长连接完成数据的交互。)

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

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

相关文章

边缘计算应用实践心得

当数据中心的光纤开始承载不了爆炸式增长的物联网数据流时,边缘计算就像毛细血管般渗透进现代数字肌理的末梢。这种将算力下沉到数据源头的技术范式,本质上是对传统云计算中心化架构的叛逆与补充——在智能制造车间里,实时质检算法直接在工业…

EXCEL如何快速批量给两字姓名中间加空格

EXCEL如何快速批量给姓名中间加空格 优点:不会导致排版混乱 缺点:无法输出在原有单元格上,若需要保留原始数据,可将公式结果复制后“选择性粘贴为值” 使用场景:在EXCEL中想要快速批量给两字姓名中间加入空格使姓名对…

Jenkins | Linux环境部署Jenkins与部署java项目

1. 部署jenkins 1.1 下载war包 依赖环境 jdk 11 下载地址: https://www.jenkins.io/ 依赖环境 1.2 启动服务 启动命令 需要注意使用jdk11以上的版本 直接启动 # httpPort 指定端口 #-Xms2048m -Xmx4096m 指定java 堆内存初始大小 与最大大小 /usr/java/jdk17/bin/java…

react私有样式处理

react私有样式处理 Nav.jsx Menu.jsx vue中通过scoped来实现样式私有化。加上scoped,就属于当前组件的私有样式。 给视图中的元素都加了一个属性data-v-xxx,然后给这些样式都加上属性选择器。(deep就是不加属性也不加属性选择器) …

UDP/TCP协议全解

目录 一. UDP协议 1.UDP协议概念 2.UDP数据报格式 3.UDP协议差错控制 二. TCP协议 1.TCP协议概念 2.三次握手与四次挥手 3.TCP报文段格式(重点) 4.流量控制 5.拥塞控制 一. UDP协议 1.UDP协议概念 当应用层的进程1要向进程2传输报文&#xff…

Duix.HeyGem:以“离线+开源”重构数字人创作生态

在AI技术快速演进的今天,虚拟数字人正从高成本、高门槛的专业领域走向大众化应用。Duix.HeyGem 数字人项目正是这一趋势下的杰出代表。该项目由一支拥有七年AI研发经验的团队打造,通过放弃传统3D建模路径,转向真人视频驱动的AI训练模型,成功实现了低成本、高质量、本地化的…

ubuntu22.04安装megaton

前置 sudo apt-get install git cmake ninja-build generate-ninja安装devkitPro https://blog.csdn.net/qq_39942341/article/details/148388639?spm1001.2014.3001.5502 安装cargo https://blog.csdn.net/qq_39942341/article/details/148387783?spm1001.2014.3001.5501 …

Windows应用-GUID工具

下载本应用 我们在DirectShow和媒体基础程序的调试中,将会遇到大量的GUID,调试窗口大部分情况下只给出GUID字符串,此GUID代表什么,我们无从得知。这时,就需要此“GUID工具”,将GUID字符串翻译为GUID定义&am…

vue+element-ui一个页面有多个子组件组成。子组件里面有各种表单,实现点击enter实现跳转到下一个表单元素的功能。

一个父组件里面是有各个子组件的form表单组成的。 我想实现点击enter。焦点直接跳转到下一个表单元素。 父组件就是由各个子组件构成 子组件就像下图一样的都有个el-form的表单。 enterToTab.js let enterToTab {}; (function() {// 返回随机数enterToTab.addEnterListener …

Vehicle HAL(5)--vhal 实现设置属性的流程

目录 1. ard11 vhal 设置属性的时序图 CarService > vhal > CarService 2. EmulatedVehicleHal::set(xxx) 的实现 本文介绍ard11的vhal属性设置流程图。 1. ard11 vhal 设置属性的时序图 CarService > vhal > CarService 2. EmulatedVehicleHal::set(xxx) 的实现…

WebRTC中的几个Rtp*Sender

一、问题: webrtc当中有几个比较相似的类,看着都是发送RTP数据包的,分别是:RtpPacketToSend 和RtpSenderVideo还有RtpVideoSender以及RTPSender,这说明什么呢?首先,说明我会很多连词&#xff0…

代码随想录算法训练营第十一天 | 150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素、栈与队列总结

150. 逆波兰表达式求值--后缀表达式 力扣题目链接(opens new window) 根据 逆波兰表示法,求表达式的值。 有效的运算符包括 , - , * , / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。 说明: 整数除法只保留整数部分。 给…

IDEA202403 设置主题和护眼色

文章目录 背景一、设置主题二、设置背景豆沙绿三、设置控制台颜色 背景 在用IDEA进行开发时,长时间对着屏幕,不费眼是及其重要 一、设置主题 默认的主题是 Dark 暗黑,可更改为其他,如Light 高亮 位置:编辑栏【files…

无人机螺旋桨平衡方法详解

螺旋桨平衡对于优化无人机性能、可靠性和使用寿命至关重要。不平衡的螺旋桨会产生过度振动,导致推力效率降低、噪音增大,并加速轴承和传感器的磨损。 螺旋桨平衡可通过三种方式实现:静态平衡、动态平衡和气动平衡。 静态与动态平衡是通过在…

基于51单片机的车内防窒息检测报警系统

目录 具体实现功能 设计介绍 资料内容 全部内容 资料获取 具体实现功能 具体实现功能: (1)检测车内温度及二氧化碳浓度并用lcd1602实时显示。 (2)当人体红外传感器检测到车内有人,且温度或二氧化碳浓度…

Flask-Babel 使用示例

下面创建一个简单的 Flask-Babel 示例,展示如何在 Flask 应用中实现国际化和本地化功能。这个示例将包括多语言支持(中文和英文)、语言切换功能以及翻译文本的使用。 项目结构 我们将创建以下文件结构: 1. 首先,创…

国标GB28181视频平台EasyGBS视频实时监控系统打造换热站全景可视化管理方案

一、方案背景​ 在城市供热体系中,换热站作为连接热源与用户的核心枢纽,其运行稳定性直接影响供热质量。面对供热规模扩大与需求升级,传统人工巡检模式暴露出效率低、响应慢、监测不足等问题。基于GB28181协议的EasyGBS视频实时监控系统&…

docker生命周期

进入容器里面 docker pull ubuntu # 获取ubtuntu镜像 docker run ubtuntu # -i 交互式命令操作,-t 开启一个终端 bash 进入容器后,执行的命令 docker run -it ubtuntu bash

鸿蒙缺少WMIC missing WMIC

在DecEco Studio中选择模拟器的时候会弹出“可能会导致设备管理功能失效。请检查并安装 WMIC”。 在启动鸿蒙模拟器时报:missing WMIC missing WMIC lt may cause the device management function to fail. Please check and install WMIC. 解决方案&#xff1a…

Spring Boot 使用 SLF4J 实现控制台输出与分类日志文件管理

概述 在日常的 Java 项目开发中,日志是最重要的调试与排查手段之一。为了便于开发时实时查看,同时在生产中追踪问题,我们通常希望实现以下日志管理目标: ✅ 控制台实时输出日志,方便开发调试✅ 日志根据级别分类保存…