当前位置: 首页 > news >正文

webrtc-m79-测试peerconnectionserver的webclient-p2p-demo

1 背景

webrtc的代码中有peerconnectionclient和peerconnectionserver的例子,但是没有对应的web端的例子,这里简单的写了一个测试例子,具体如下:

2 具体操作

2.1 操作流程

2.2 测试效果

使用webclient与peerconnectionclient的测试效果如下:

3 前端代码

<html>
<head><title>webclient p2p demo</title><meta charset="utf-8"><style>.left_part {width: 50%;float: left;}.right_part {width: 50%;float: right;overflow-y: scroll;}</style><script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head><body><div class="right_part" id="left_part_container"><div>SignalServer:<input type="text" id="signal_url" value="127.0.0.1:8888"><button id="btn_sign_in">登入</button><button id="btn_sign_out">登出</button><br><input type="text" id="selected_peerid_for_p2p" disabled value="不允许修改的文本"><button id="btn_start_p2p" disabled>start_p2p</button></div><br><table id="PeersTable"><thead><tr><th>Name</th><th>PeerId</th><th>Status</th></tr></thead></table></div><div class="left_part" id="left_part_container"><video controls autoplay id="rtc_video_play" height="500" style="width:100%"></video></div><script type="text/javascript">var myselfPeerId = -1;var pc = new RTCPeerConnection({ "offerExtmapAllowMixed": false });var datachannel = null;var stream = new MediaStream();async function initPC() {pc.addTransceiver("audio", {direction: "recvonly"});pc.addTransceiver("video", {direction: "recvonly"});pc.onconnectionstatechange = function(event){console.log("connection state change: ", pc.connectionState);};pc.onicecandidate = async (ev) => {console.log('=======>' + JSON.stringify(ev.candidate));        };pc.ontrack = function(event) {stream.addTrack(event.track);                         };datachannel = pc.createDataChannel('chat');datachannel.onopen = function(event) {console.log("datachannel onopen: ", event.data);}datachannel.onmessage = function(event) {console.log("receive message: ", event.data);}datachannel.onerror = function(event) {console.log("datachannel error: ", event.data);}datachannel.onclose = function(event) {console.log("datachannel close: ");}                    }async function startP2P(signal_url) {initPC();var offer = await pc.createOffer();await pc.setLocalDescription(offer);let sendOfferPromise = await fetch(signal_url, {"method": "POST","body": JSON.stringify(offer)});if (sendOfferPromise.ok) {console.log("send offer: " + JSON.stringify(offer));                         } else {alert("HTTP-Error: " + sendOfferPromise.status);}               }   async function nfyFromSignal(nfyPromise) {let nfyString = await nfyPromise.text();if (nfyString.includes("answer")) {console.log("receive answer: " + nfyString);pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(nfyString)));} else if (nfyString.includes("candidate")) {console.log("receive candidate: " + nfyString);pc.addIceCandidate(new RTCIceCandidate(JSON.parse(nfyString)));} else {let peersString = nfyString;// console.log("rsp: ", peersString)let peersChunk = peersString.split("\n");for (let i=0; i<peersChunk.length && peersChunk[i].length>0; ++i) {const peerColumns = peersChunk[i].split(",");// console.log("index: " + i + ", data: " + peerColumns)// for example: kevin@home-pc,36,1// peerColumns[0]: peer_name// peerColumns[1]: peer_id// peerColumns[2]: peer_status// table's column index starts from 1, not 0const row_find_peer_id = $("#PeersTable tr:has(td:nth-child(2):contains('" + peerColumns[1] + "'))");if (row_find_peer_id.length > 0) {console.log("peerid:" + peerColumns[1] + ", status change from " + row_find_peer_id.find('td:nth-child(3)').text() + " to " + peerColumns[2]);row_find_peer_id.find('td:nth-child(3)').text(peerColumns[2]);continue;}const row_find_peer_name = $("#PeersTable tr:has(td:nth-child(1):contains('" + peerColumns[0] + "'))");if (row_find_peer_name.length > 0) {console.log("peerid:" + peerColumns[1] + ", status change from " + row_find_peer_name.find('td:nth-child(3)').text() + " to " + peerColumns[2]);row_find_peer_name.find('td:nth-child(2)').text(peerColumns[1]);row_find_peer_name.find('td:nth-child(3)').text(peerColumns[2]);continue;}                  const row_peer = $("<tr>");row_peer.append($("<td>").text(peerColumns[0]));row_peer.append($("<td>").text(peerColumns[1]));row_peer.append($("<td>").text(peerColumns[2]));$("#PeersTable").append(row_peer);}                }}async function pendingWait(myself_peerid) {const signal_url = document.getElementById("signal_url").value;while (true) {let v = await fetch(`http://${signal_url}/wait?peer_id=${myself_peerid}`);nfyFromSignal(v);}}$('#btn_sign_in').on('click', async () => {const signal_url = document.getElementById("signal_url").value;let signinResultPromise = await fetch(`http://${signal_url}/sign_in`);if (signinResultPromise.ok) {myselfPeerId = parseInt(signinResultPromise.headers.get("Pragma"));console.log("my peerid is: " + myselfPeerId);nfyFromSignal(signinResultPromise);pendingWait(myselfPeerId);               } else {alert("HTTP-Error: " + signinResultPromise.status);}})        $('#btn_sign_out').on('click', async () => {$("#PeersTable tbody").empty();const signal_url = document.getElementById("signal_url").value;let signoutResultPromise = await fetch(`http://${signal_url}/sign_out?peer_id=${myselfPeerId}`);if (signoutResultPromise.ok) {console.log("sign_out: " + myselfPeerId + " successful");       } else {alert("HTTP-Error: " + signoutResultPromise.status);}})$('#PeersTable').on('click', 'tr', function() {const row_selected = $(this);const row_selected_peer_id = parseInt(row_selected.find('td:nth-child(2)').text());if (row_selected_peer_id === myselfPeerId) {console.log("You should not choose yourself [" + myselfPeerId + "] to start p2p");$("#btn_start_p2p").prop("disabled", true);return;}const row_selected_peer_id_status = parseInt(row_selected.find('td:nth-child(3)').text());if (row_selected_peer_id_status === 1) {console.log("selected peerid: " + row_selected_peer_id);$('#selected_peerid_for_p2p').val(row_selected_peer_id);$("#btn_start_p2p").prop("disabled", false);                } else {console.log("The peer [" + row_selected_peer_id + "] you choose is offline");$("#btn_start_p2p").prop("disabled", true);}})$('#btn_start_p2p').on('click', async () => {const signal_url = document.getElementById("signal_url").value;const remote_peer_id = $('#selected_peerid_for_p2p').val();const sendmsg_url = `http://${signal_url}/message?peer_id=${myselfPeerId}&to=${remote_peer_id}`;console.log("sendmsg url: " + sendmsg_url);// $('#rtc_video_play').show();// $('#rtc_video_play').prop('muted', false);$('#rtc_video_play').prop('srcObject', stream);console.log("Start P2P from [" + myselfPeerId + "] to [" + remote_peer_id + "]");startP2P(sendmsg_url);})</script>
</body>
</html>

相关文章:

webrtc-m79-测试peerconnectionserver的webclient-p2p-demo

1 背景 webrtc的代码中有peerconnectionclient和peerconnectionserver的例子&#xff0c;但是没有对应的web端的例子&#xff0c;这里简单的写了一个测试例子&#xff0c;具体如下&#xff1a; 2 具体操作 2.1 操作流程 2.2 测试效果 使用webclient与peerconnectionclient的…...

C#,《小白学程序》第十五课:随机数(Random)第二,统计学初步,数据统计的计算方法与代码

1 文本格式 /// <summary> /// 《小白学程序》第十五课&#xff1a;随机数&#xff08;Random&#xff09;第二&#xff0c;统计学初步&#xff0c;数据统计的计算方法与代码 /// 用随机数做简单的统计并用图形显示统计结果。 /// </summary> /// <param name&q…...

C# 子类如何访问子类的方法(同一父类)

在继承关系中&#xff0c;子类可以通过创建另一个子类的对象来访问其方法。下面是一个示例&#xff0c;展示了子类如何访问另一个子类的方法&#xff1a; public class Animal {public virtual void Speak(){Console.WriteLine("我是动物。");} }public class Cat :…...

《Docker 容器化的艺术:深入理解容器技术》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…...

gitlab配置hook,commit message的时候校验提交的信息

在 GitLab 中配置 Webhook 来调用 Java 接口以校验 commit 信息&#xff0c;是很多公司的一些要求&#xff0c;因为提交信息的规范化是必要的 不阻止commit的版本 在 GitLab 项目中进入设置页面。 在左侧导航栏中选择 “Webhooks”&#xff08;Web钩子&#xff09;。 在 We…...

ssh远程管理服务

ssh远程管理服务是什么 SSH是一个安全协议&#xff0c;在进行数据传输时&#xff0c;会对数据包进行加密处理&#xff0c;加密后在进行数据传输。确保了数据传输安全, 那SSH服务主要功能有哪些呢&#xff1f; 1.提供远程连接服务器的服务 1&#xff09;linux远程连接协议&…...

C语言顺序表

文章目录 前言线性表顺序表静态顺序表动态顺序表 接口实现 前言 我们先补一下上篇博客落下的知识点&#xff1a; 首先说一下斐波那契的时间复杂度和空间复杂度&#xff1a; long long Fac(size_t N) {if(0 N)return 1;return Fac(N-1)*N; }还是说一下size_t代表的类型是unsi…...

滑动窗口详解

滑动窗口本质其实也是一种双指针算法&#xff0c;只是因为它维护的区间随着遍历的进行在不停变化&#xff0c;所以形象地称为“滑动窗口” 一、⻓度最⼩的⼦数组 题目要求找到满足条件的长度最小的子数组&#xff0c;我们先来想想暴力的做法&#xff0c;再来想想能不能优化&am…...

JAVA -华为真题-分奖金

需求: 公司老板做了一笔大生意&#xff0c;想要给每位员工分配一些奖金&#xff0c;想通过游戏的方式来决定每个人分多少钱。按照员工的工号顺序&#xff0c;每个人随机抽取一个数字。按照工号的顺序往后排列&#xff0c;遇到第一个数字比自己数字大的&#xff0c;那么&#xf…...

第二章:25+ Python 数据操作教程(第十八节如何使用 Matplotlib 库在 python 中执行绘图和数据可视化)持续更新中

本教程概述了如何使用 Matplotlib 库在 python 中执行绘图和数据可视化。这篇文章的目的是让您熟悉该库的基础知识和高级绘图功能。它包含几个示例,将为您提供使用 Python 生成绘图的实践经验。 目录 什么是 Matplotlib? Matplotlib 基础知识<...

XShell7 + Xftp7 + IDEA 打包MapReduce程序到集群运行

参考博客 【MapReduce打包成jar上传到集群运行】http://t.csdn.cn/2gK1d 【Xshell7/Xftp7 解决强制更新问题】http://t.csdn.cn/rxiBG IDEA打包MapReduce程序 这里的打包是打包整个项目&#xff0c;后期等学会怎么打包单个指定的mapreduce程序再来更新博客。 1、编译打包 …...

微软D365 入门文章汇总以及各项认证介绍(持续跟新.....)

介绍 希望入门D365的同学们&#xff0c;需要具备的知识点&#xff0c;涉及C#&#xff0c;WebApi&#xff0c;前端知识&#xff0c;Power Platform等知识&#xff0c;以及Azure的知识点等&#xff0c;需要有了解。 实施Microsoft Dynamics 365 CE &#xff08;12章&#xff09;…...

vscode搭建Django自带后台管理系统

文章目录 一、django自带的后台管理系统1. 建表2. 后台管理系统2.1 创建账号2.2 运行后台2.3 登录 二、模版渲染1. 直接将数据渲染到页面2. 数据传递给js 三、数据库1. 查看当前数据库2. 创建UserInfo数据表3. Django rest framework配置 四、vue前端搭建1. 在Django项目的根目…...

Verilog零基础入门(边看边练与测试仿真)-时序逻辑-笔记(4-6讲)

文章目录 第四讲第五讲第六讲 第四讲 1、计数器 代码&#xff1a; //计数器 timescale 1ns/10ps module counter(clk,res,y); input clk; input res; output[7:0] y;reg[7:0] y; wire[7:0] sum;//1运算的结果&#xff08;1&#xff0…...

2023-09-12力扣每日一题

链接&#xff1a; 1462. 课程表 IV 题意 一个pair<int,int>表示a是b的前置 进行n次查询&#xff0c;查询q是否是p的前置&#xff08;可以不是直接前置&#xff09; 解&#xff1a; 就是要把01、12、13这种能转换出02、03&#xff0c;弗洛伊德即可 无环无负权 实际…...

leetcode面试题:交换和(三种方法实现)

交换和&#xff1a; 给定两个整数数组&#xff0c;请交换一对数值&#xff08;每个数组中取一个数值&#xff09;&#xff0c;使得两个数组所有元素的和相等。 返回一个数组&#xff0c;第一个元素是第一个数组中要交换的元素&#xff0c;第二个元素是第二个数组中要交换的元…...

前端可视化界面开发技术:实战与优化

引言 在当今的互联网时代&#xff0c;数据可视化已经成为信息展示和交互的重要方式。特别是在前端开发领域&#xff0c;可视化界面的应用越来越广泛&#xff0c;涉及到数据监控、分析和决策等多种场景。本文将深入探讨前端可视化界面开发的关键技术&#xff0c;通过实例解析提…...

Python实现机器学习(下)— 数据预处理、模型训练和模型评估

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。本门课程将介绍人工智能相关概念&#xff0c;重点讲解机器学习原理机器基本算法&#xff08;监督学习及非监督学习&#xff09;。使用python&#xff0c;结合sklearn、Pycharm进行编程&#xff0c;介绍iris&#xff08;鸢尾…...

树结构处理,list和tree互转

1、实体类 package com.iot.common.test.entity;import lombok.Data;import java.util.List;/*** description:* author:zilong* date:2023/9/8*/ Data public class Node {//idprivate String id;//父节点idprivate String pId;//名称private String name;//编码private Stri…...

可视化大屏设计模板 | 主题皮肤(报表UI设计)

下载使用可视化大屏设计模板&#xff0c;减少重复性操作&#xff0c;提高报表制作效率的同时也确保了报表风格一致&#xff0c;凸显关键数据信息。 软件&#xff1a;奥威BI系统&#xff0c;又称奥威BI数据可视化工具 所属功能板块&#xff1a;主题皮肤上传下载&#xff08;数…...

C#元组类型简介

元组是 C# 7.0 引入的轻量级数据结构&#xff0c;用于临时组合多个值&#xff0c;无需定义专门的类或结构。 元组是有序的数据结构&#xff0c;成员按声明/创建时的顺序排列。&#xff08;这里的元组只指值元组&#xff09;元组类型在C#7.0前是有一个专门的内置类型&#xff0c…...

对lsof、tcpdump、strace命令的简单记录

1. lsof (List Open Files) —— “谁占用了资源&#xff1f;” 核心哲学&#xff1a;Linux 中一切皆文件&#xff08;包括磁盘文件、网络 Socket、设备&#xff09;。 常用操作&#xff1a;lsof -i :15000&#xff1a;查看指定端口的进程占用及连接状态&#xff08;LISTEN/EST…...

终极大脑训练指南:5个简单步骤用BrainWorkshop提升你的认知能力

终极大脑训练指南&#xff1a;5个简单步骤用BrainWorkshop提升你的认知能力 【免费下载链接】brainworkshop Continued development of the popular brainworkshop game 项目地址: https://gitcode.com/gh_mirrors/br/brainworkshop BrainWorkshop是一款专业的免费开源大…...

Google 2026 AI全家桶升级:企业管理员必须在48小时内完成的3项策略校准与2项合规备案

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Google 2026 AI全家桶升级全景图 2026年&#xff0c;Google正式发布新一代AI基础设施矩阵——“Project Aether”&#xff0c;标志着其AI全家桶从模块化协同迈向原生融合时代。核心升级聚焦于模型、工具…...

制造业财务场景AI自动化方案,主流厂商横向对比 —— 2026企业级智能体选型全景盘点

进入2026年&#xff0c;全球制造业正处于从“自动化”向“智能共生”跨越的关键节点。 财务部门作为企业的数据中枢&#xff0c;其AI自动化方案已不再局限于早期的OCR识别或简单的流程脚本。 随着大模型&#xff08;LLM&#xff09;与智能体&#xff08;Agent&#xff09;技术的…...

告别繁琐操作:一键下载国家中小学智慧教育平台电子课本的智能解决方案

告别繁琐操作&#xff1a;一键下载国家中小学智慧教育平台电子课本的智能解决方案 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具&#xff0c;帮助您从智慧教育平台中获取电子课本的 PDF 文件网址并进行下载&#xff0c;让您更方便地获取课本内…...

从布朗运动到伊藤公式:金融随机世界的建模基石

1. 从花粉运动到股票价格&#xff1a;布朗运动的金融启示 1827年&#xff0c;英国植物学家罗伯特布朗在显微镜下观察到花粉颗粒在水中的不规则舞动&#xff0c;这个看似简单的物理现象却在80年后被爱因斯坦用数学语言精确描述。有趣的是&#xff0c;当我们将显微镜换成股票行情…...

告别PLC!用Python+ModbusTCP玩转FactoryIO仿真(附完整代码与可视化界面)

PythonModbusTCP工业仿真实战&#xff1a;从零构建FactoryIO智能分拣系统 工业自动化领域正在经历一场静默革命——传统PLC的垄断地位首次被通用编程语言打破。去年某国际自动化展会上&#xff0c;一位工程师仅用200行Python代码就复现了某品牌PLC的复杂流水线控制逻辑&#xf…...

Baetyl开源社区贡献指南:如何参与边缘计算框架的代码与文档开发

Baetyl开源社区贡献指南&#xff1a;如何参与边缘计算框架的代码与文档开发 【免费下载链接】baetyl Extend cloud computing, data and service seamlessly to edge devices. 项目地址: https://gitcode.com/gh_mirrors/ba/baetyl 欢迎来到Baetyl开源边缘计算框架的贡献…...

思科路由器远程管理保姆级教程:从IP配置到Telnet/SSH登录全流程(避坑line vty和密码设置)

思科路由器远程管理全流程实战指南&#xff1a;从基础配置到安全登录 刚接触思科设备时&#xff0c;最让人头疼的莫过于那一连串看似晦涩的命令行操作。记得我第一次尝试配置路由器远程访问时&#xff0c;明明按照教程一步步操作&#xff0c;却始终无法通过Telnet连接&#xff…...