aioice里面candidate固定UDP端口测试
环境:
aioice0.9.0
问题描述:
aioice里面candidate固定UDP端口测试
解决方案:
/miniconda3/envs/nerfstream/lib/python3.10/site-packages/aioice
import hashlib
import ipaddress
import random
from typing import Optional
import logging# 配置日志级别,默认为 INFO,可改为 DEBUG 查看详细调试信息
logging.basicConfig(level=logging.INFO)class Candidate:"""表示一个 ICE 候选者,包括固定端口功能和多种优化。"""FIXED_PORT = 59990 # 定义固定端口def __init__(self,foundation: str,component: int,transport: str,priority: int,host: str,port: Optional[int] = None, # 端口可以是 None,将被替换为固定端口type: str = "host",related_address: Optional[str] = None,related_port: Optional[int] = None,tcptype: Optional[str] = None,generation: Optional[int] = None,) -> None:"""初始化候选者对象,并强制使用固定端口。"""self.foundation = foundationself.component = componentself.transport = transportself.priority = priorityself.host = hostself.port = self.get_fixed_port() if port is None else port # 设置为固定端口或提供的端口self.type = typeself.related_address = related_addressself.related_port = related_portself.tcptype = tcptypeself.generation = generation# 输出候选者信息到日志logging.info(f"创建候选者:host={self.host}, port={self.port}, type={self.type}")@classmethoddef get_fixed_port(cls) -> int:"""返回固定端口值,并记录日志。"""fixed_port = cls.FIXED_PORTlogging.debug(f"Returning fixed port: {fixed_port}")return fixed_port@classmethoddef from_sdp(cls, sdp: str):"""从 SDP 字符串中解析一个 ICE 候选者。示例 SDP:'6815297761 1 udp 659136 192.168.1.1 12345 typ host'"""bits = sdp.split()if len(bits) < 8:raise ValueError("SDP 描述字段不足")kwargs = {"foundation": bits[0],"component": int(bits[1]),"transport": bits[2],"priority": int(bits[3]),"host": bits[4],"port": cls.get_fixed_port(), # 使用固定端口"type": bits[7],}# 提取 SDP 中的附加信息for i in range(8, len(bits), 2):if bits[i] == "raddr":kwargs["related_address"] = bits[i + 1]elif bits[i] == "rport":kwargs["related_port"] = int(bits[i + 1])elif bits[i] == "tcptype":kwargs["tcptype"] = bits[i + 1]elif bits[i] == "generation":kwargs["generation"] = int(bits[i + 1])return cls(**kwargs)def to_sdp(self) -> str:"""返回一个适用于 SDP 的字符串表示形式。"""sdp = f"{self.foundation} {self.component} {self.transport} {self.priority} {self.host} {self.port} typ {self.type}"if self.related_address is not None:sdp += f" raddr {self.related_address}"if self.related_port is not None:sdp += f" rport {self.related_port}"if self.tcptype is not None:sdp += f" tcptype {self.tcptype}"if self.generation is not None:sdp += f" generation {self.generation}"return sdpdef can_pair_with(self, other) -> bool:"""判断本地候选者是否可以与远程候选者配对。配对条件:- 组件相同- 使用相同的传输协议- IP 地址版本相同"""a = ipaddress.ip_address(self.host)b = ipaddress.ip_address(other.host)return (self.component == other.componentand self.transport.lower() == other.transport.lower()and a.version == b.version)def __repr__(self) -> str:"""返回候选者的字符串表示形式。"""return f"Candidate({self.to_sdp()})"# 工具函数部分
def candidate_foundation(candidate_type: str, candidate_transport: str, base_address: str) -> str:"""计算候选者的 Foundation(基础标识符)。"""key = f"{candidate_type}|{candidate_transport}|{base_address}"return hashlib.md5(key.encode("ascii")).hexdigest()def candidate_priority(candidate_component: int, candidate_type: str, local_pref: int = 65535) -> int:"""计算候选者优先级。优先级从高到低的顺序为:host > srflx > relay。"""type_preferences = {"host": 126, # Host 类型优先级最高"srflx": 100, # Server reflexive 类型"relay": 0, # Relay 类型优先级最低}type_pref = type_preferences.get(candidate_type, 0)return (1 << 24) * type_pref + (1 << 8) * local_pref + (256 - candidate_component)# 测试代码部分
if __name__ == "__main__":# 测试创建候选者candidate = Candidate(foundation="1",component=1,transport="udp",priority=candidate_priority(1, "host"),host="192.168.168.77", # 使用你的本地 IP 地址type="host",)print(candidate) # 打印候选者信息print(candidate.to_sdp()) # 打印 SDP 字符串# 测试从 SDP 创建候选者sdp_example = "1 1 udp 100 192.168.1.1 12345 typ host"candidate_from_sdp = Candidate.from_sdp(sdp_example)print(candidate_from_sdp) # 打印解析后的候选者print(candidate_from_sdp.to_sdp()) # 打印 SDP 字符串# 模拟 WebRTC 应用程序创建多个候选者candidates = [Candidate(foundation=str(i),component=1,transport="udp",priority=candidate_priority(1, "host"),host=f"192.168.1.{i % 255}", # 使用不同的 IP 地址模拟不同设备type="host",)for i in range(1, 6)]for c in candidates:print(c)
运行没有成功

相关文章:
aioice里面candidate固定UDP端口测试
环境: aioice0.9.0 问题描述: aioice里面candidate固定UDP端口测试 解决方案: /miniconda3/envs/nerfstream/lib/python3.10/site-packages/aioice import hashlib import ipaddress import random from typing import Optional import…...
Git使用教程-分支使用/合并分支提交
Git使用教程-分支使用 文章目录 Git使用教程-分支使用一、分支(branch)的基本操作:二、查看分支:参考 一、分支(branch)的基本操作: git clone https://.git git status …...
单元测试使用记录
什么是单元测试 简单来说就是对一个类中的方法进行测试,对输出的结果检查判断是否符合预期结果 但是在多年的工作中,从来没有哪个项目中真正系统的用到了单元测试,因此对它还是很陌生的,也就造成更加不会在项目中区使用它。 如何…...
LabVIEW实时信号采集与频谱分析
系统通过LabVIEW与PXIe硬件结合,实现高精度模拟信号的实时采集、频谱分析与可视化显示。核心功能包括采样率配置、快速傅里叶变换(FFT)、功率谱图生成及动态缩放调整,同时支持信号平均与噪声抑制。系统设计灵活,适用于…...
OpenCV(python)从入门到精通——运算操作
加法减法操作 import cv2 as cv import numpy as npx np.uint8([250]) y np.uint8([10])x_1 np.uint8([10]) y_1 np.uint8([20])# 加法,相加最大只能为255 print(cv.add(x,y))# 减法,相互减最小值只能为0 print(cv.subtract(x_1,y_1))图像加法 import cv2 as…...
基础2:值类型与右值引用
1.函数返回 在讲解右值之前,要知道下面这个函数要进行几次拷贝以及为什么? int get_x() {int x 20;return x; }int aget_x(); 答案:两次 # 第一次 int tmpa; # 第二次 int xtmp;2.左值与右值 🍏2.1 能取地址操作的就是左值 …...
GitHub年度报告发布!Python首次超越JavaScript
全球开发者数量激增,GenAI 项目呈爆炸式增长趋势,推动编程语言的应用格局也发生了巨大变化,最新的 GitHub Octoverse 报告来了! 1、Python 首次超越 JavaScript,成为 GitHub 平台最顶级编程语言 不同于流传“AI 即将取…...
EdgeX Message Bus 消息总线
EdgeX Message Bus 消息总线 一、概述 EdgeX MessageBus 内部消息总线,用于 EdgeX 服务之间的内部通信。 EdgeX 服务是指来自 EdgeX 的任何核心/支持/应用程序/设备服务或使用 EdgeX SDK 构建的任何自定义应用程序或设备服务。 EdgeX MessageBus 用于内部 EdgeX 服务与服务之间…...
【JavaEE进阶】关于Maven
目录 🌴什么是Maven 🌲为什么要学Maven 🎍创建一个Maven项目 🎄Maven核心功能 🚩项目构建 🚩依赖管理 🎋Maven Help插件 🍀Maven 仓库 🚩本地仓库 Ὢ…...
YOLOv9-0.1部分代码阅读笔记-autoanchor.py
autoanchor.py utils\autoanchor.py 目录 autoanchor.py 1.所需的库和模块 2.def check_anchor_order(m): 3.def check_anchors(dataset, model, thr4.0, imgsz640): 4.def kmean_anchors(dataset./data/coco128.yaml, n9, img_size640, thr4.0, gen1000, verboseTrue…...
Electronjs+Vue如何开发PC桌面客户端(Windows,Mac,Linux)
electronjs官网 https://www.electronjs.org/zh/ Electron开发PC桌面客户端的技术选型非常适合已经有web前端开发人员的团队。能够很丝滑的过渡。 Electron是什么? Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium 和 Node.…...
谷歌浏览器 安装谷歌浏览器特定版本后禁止自动更新
问题描述 我们通过离线安装谷歌浏览器后,第一次打开浏览器时会默认下载最新版本,等到我们重启浏览器后它会自动更新。在项目中为了能固定浏览器版本,所以要禁止谷歌浏览器的更新,网上找了好多方法都没用,自己摸索出来…...
Linux计算时间差
Linux计算时间差 1、Linux计算时间差2、时间差的应用 1、Linux计算时间差 在Linux中,计算时间差通常是为了统计、监控或调试。时间差可以用来衡量任务执行的时间,或者两个事件之间的间隔。例如,响应时间、执行时间、定时任务与延时处理等 以…...
Python的3D可视化库【vedo】2-5 (plotter模块) 坐标转换、场景导出、添加控件
文章目录 4 Plotter类的方法4.7 屏幕和场景中的坐标点转换4.7.1 屏幕坐标转为世界坐标4.7.2 世界坐标转为屏幕坐标4.7.3 屏幕坐标取颜色 4.8 导出4.8.1 导出2D图片4.8.2 导出3D文件 4.9 添加控件4.9.1 添加内嵌子窗口4.9.2 添加选择区4.9.3 添加比例尺4.9.4 为对象添加弹出提示…...
【VUE】13、安装nrm管理多个npm源
nrm(npm registry manager)是一个 npm 源管理器,它允许用户快速地在不同的 npm 源之间进行切换,以提高包管理的速度和效率。以下是对 nrm 使用的详细介绍: 1、安装nrm 在使用 nrm 之前,需要先确保已经安装…...
【SQL/MySQL 如何使用三种触发器】SQL语句实例演示
触发器介绍 – 触发器是与表有关的数据库对象,指在insert/update/delete之前(BEFORE)或之后(AFTER),触发并执行触发器中定义的SQL语句集合。 – 使用别名OLD和NEW来引用触发器中发生变化的记录内容,这与其他的数据库是相似的。现在触发器还只…...
Docker容器五种网络驱动模式详解
Docker 网络用于在容器之间以及容器与外部网络之间提供通信功能。它允许容器在隔离的网络环境中运行,同时也能根据需要与其他容器或外部网络进行交互。通过使用网络驱动,Docker 可以创建不同类型的网络,以满足各种应用场景的需求。 传统上&am…...
netfilter简介及流程图
Netfilter 是 Linux 内核中用于网络包过滤和操作的框架,由 Rusty Russell 于1998年创立,旨在改进旧的 ipchains 和 ipfwadm 实现。它采用模块化设计,具有良好可扩展性,并在2000年3月合并进Linux 2.3.x内核版本。 Netfilter的主要…...
Vue 前端代码规范
在 Vue 前端开发中,遵循代码规范可以提高代码的可读性、可维护性和团队协作效率。以下是一些详细的 Vue 前端代码规范,涵盖了多个方面: ### 1. **项目结构** - **目录结构**:- src/ 目录下应包含 components/、views/、store/、router/、ass…...
JAVA:组合模式(Composite Pattern)的技术指南
1、简述 组合模式(Composite Pattern)是一种结构型设计模式,旨在将对象组合成树形结构以表示“部分-整体”的层次结构。它使客户端对单个对象和组合对象的使用具有一致性。 设计模式样例:https://gitee.com/lhdxhl/design-pattern-example.git 2、什么是组合模式 组合模式…...
5分钟搞定安卓APK签名:SignatureTools图形化签名工具终极指南
5分钟搞定安卓APK签名:SignatureTools图形化签名工具终极指南 【免费下载链接】SignatureTools 🎡使用JavaFx编写的安卓Apk签名&渠道写入工具,方便快速进行v1&v2签名。 项目地址: https://gitcode.com/gh_mirrors/si/SignatureTool…...
别再死记硬背GPIO寄存器了!用STM32 HAL库和CubeMX快速实现LED流水灯与按键控制
解放双手:用STM32CubeMX和HAL库玩转GPIO控制 在嵌入式开发的世界里,GPIO控制就像学习编程时的"Hello World"一样基础而重要。但有多少开发者还在为记忆繁琐的寄存器配置而头疼?当项目周期压缩到以天为单位计算时,我们是…...
HFSS扫频实战:三种扫频类型的选择策略与性能对比
1. HFSS扫频分析基础:为什么需要扫频? 刚接触HFSS仿真时,很多工程师都会疑惑:为什么不能直接计算目标频点的S参数?这个问题就像用相机拍照——单点频率仿真相当于只拍一张静态照片,而扫频分析则是录制一段视…...
DsHidMini技术揭秘:Windows平台下DualShock 3控制器用户空间驱动实现方案
DsHidMini技术揭秘:Windows平台下DualShock 3控制器用户空间驱动实现方案 【免费下载链接】DsHidMini Virtual HID Mini-user-mode-driver for Sony DualShock 3 Controllers 项目地址: https://gitcode.com/gh_mirrors/ds/DsHidMini 在Windows游戏生态系统中…...
3步掌握VADER情感分析:颠覆传统NLP方法的实战指南
3步掌握VADER情感分析:颠覆传统NLP方法的实战指南 【免费下载链接】vaderSentiment VADER Sentiment Analysis. VADER (Valence Aware Dictionary and sEntiment Reasoner) is a lexicon and rule-based sentiment analysis tool that is specifically attuned to s…...
领信任安全架构在安全防护能力合规性业务连续性方面的建树
从被动防御到主动免疫:零信任安全架构在安全防护能力、合规性与业务连续性三大维度的全面建树 引言:当“城墙”不再有效,新的安全范式如何证明自己? 2026年3月,一场被称为“CyberStrikeAI”的自主AI攻击战役横扫全球——完全自主的AI引擎在短短数周内攻破了55个国家的60…...
避坑指南:香橙派串口开发中orangepiEnv.txt与armbianEnv.txt的配置差异详解
香橙派串口开发实战:系统配置差异与深度调试指南 当你在深夜调试香橙派串口时,突然发现修改的配置文件毫无反应——这种经历相信不少开发者都遇到过。问题的根源往往不在于代码本身,而是隐藏在系统环境中的配置差异。本文将带你深入剖析香橙派…...
03-eMMC性能实战解析:速率模式、引脚配置与上电时序的协同设计
1. eMMC高速模式实战:HS400与HS200的带宽对决 在嵌入式系统设计中,eMMC存储的性能直接影响设备响应速度和用户体验。实测数据显示,三星KLMCG2KETM-B041芯片在HS400模式下能达到269.4MB/s的读取速度,而东芝THGBMDG5D1LBAIL同模式下…...
手把手教你给STM32H743的0.96寸OLED屏移植STemWin(裸机+FreeRTOS双版本)
STM32H743与0.96寸OLED的STemWin深度移植实战:裸机与RTOS双环境解析 在嵌入式图形界面开发领域,STemWin作为ST官方推出的图形库解决方案,以其高效的渲染性能和丰富的控件资源,成为STM32开发者构建人机界面的首选。本文将聚焦STM32…...
Galaxea R1仿人机器人硬件架构与控制系统解析
1. Galaxea R1机器人硬件架构解析Galaxea R1是一款专为家庭服务场景设计的仿人机器人平台,其硬件系统经过精心设计以满足复杂环境下的操作需求。作为机器人领域的从业者,我在实际测试中发现这套硬件架构在负载能力、运动灵活性和环境感知三个关键维度上达…...
