当前位置: 首页 > 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;数…...

Spring Boot + Vue的网上商城之客服系统实现

Spring Boot Vue的网上商城之客服系统实现 在网上商城中&#xff0c;客服系统是非常重要的一部分&#xff0c;它能够为用户提供及时的咨询和解答问题的服务。本文将介绍如何使用Spring Boot和Vue.js构建一个简单的网上商城客服系统。 思路 在本教程中&#xff0c;我们学习了…...

RabbitMQ: return机制

1. Return机制 Confirm只能保证消息到达exchange&#xff0c;无法保证消息可以被exchange分发到指定queue。 而且exchange是不能持久化消息的&#xff0c;queue是可以持久化消息。 采用Return机制来监听消息是否从exchange送到了指定的queue中 2.Java的实现方式 1.导入依赖 &l…...

记录一些奇怪的报错

错误&#xff1a;AttributeError: module distutils has no attribute version 解决方案&#xff1a; 第一步&#xff1a;pip uninstall setuptools 第二步&#xff1a;conda install setuptools58.0.4 错误&#xff1a;ModuleNotFoundError: No module named _distutils_hac…...

Ubuntu 安装redis数据库,并设置开机自启动

1、下载安装包 wget http://download.redis.io/releases/redis-7.0.9.tar.gz 2、解压 tar -zxvf redis-7.0.9.tar.gz 3、复制到解压缩的包移动到/usr/local/ sudo mv ./redis-7.0.9 /usr/local/ 4、编译 cd /usr/local/redis-7.0.9 sudo make 5、测试: 时间会比较长&#xff0…...

基于开源模型搭建实时人脸识别系统(五):人脸跟踪

继续填坑&#xff0c;之前已经讲了人脸检测&#xff0c;人脸识别实战之基于开源模型搭建实时人脸识别系统&#xff08;二&#xff09;&#xff1a;人脸检测概览与模型选型_开源人脸识别模型_CodingInCV的博客-CSDN博客&#xff0c;人脸检测是定位出画面中人脸的位置&#xff0c…...

VUE | 配置环境变量

本篇目录 1. 创建开发环境配置文件2. 创建正式环境配置文件3. 在代码中访问环境变量4. 加载环境变量 在 Vue 项目中是使用 .env 文件来定义和使用不同的环境变量&#xff0c;这些文件在 Vue 项目根目录下创建。推荐有几种环境就创建几个 .env 文件&#xff0c;下面就开发环境和…...

Dynamic-TP入门初探

背景 在使用线程池的过程中&#xff0c;会出现一些痛点&#xff1a; 代码中创建了一个线程池&#xff0c;但是不知道那几个核心参数设置多少比较合适。凭经验设置参数值&#xff0c;上线后发现需要调整&#xff0c;改代码重新发布服务&#xff0c;非常麻烦。线程池相对开发人…...

Git的基本操作:远程操作

7 Git的远程操作 远程操作主要是指&#xff0c;在不同的仓库之间进行提交和代码更改。是一个明显的对等的分布式系统。其中本地个仓库与远程仓库&#xff0c;不同的远程仓库之间都可以建立这种关系。这种关系之间的操作主要有pull和push。 远程仓库 创建SSH key远程仓库和本…...

【IOC,AOP】spring的基础概念

IOC 控制反转 对象的创建控制权转交给外部实体&#xff0c;就是控制反转。外部实体便是IOC容器。其实就是以前创建java对象都是我们new一下&#xff0c;现在我们可以把这个new交给IOC容器来做&#xff0c;new出来的对象也会交由IOC容器来管理。这个new出来的对象则称为Bean。 …...

安全实战 | 怎么用零信任防范弱密码?

防范弱密码&#xff0c;不仅需要提升安全性&#xff0c;更需要提升用户体验。 比如在登录各类业务系统时&#xff0c;我们希望员工登录不同系统不再频繁切换账号密码&#xff0c;不再需要3-5个月更换一次密码&#xff0c;也不再需要频繁的输入、记录、找回密码。 员工所有的办…...

网站做电商资质/百度自动优化

用户登录添加 购物车时候&#xff0c;发生点击添加购物车无效果问题&#xff1b; 用户登录&#xff0c;需对用户进行token 校验&#xff0c;添加购物车&#xff0c;用户购物车查询本地购物车用户账户中购物车&#xff1b; 在用户未登录状态时候是没有任何问题的&#xff0c;单单…...

wordpress 操作教程/广州网站seo地址

在子目录下仍然可以建立.gitignore文件以用于忽略子目录的文件转载于:https://www.cnblogs.com/zuoxiaobing/p/4616568.html...

网站专题页面设计欣赏/优秀的软文广告案例

注解相关 AliasFor&#xff1a;.在同个注解中为同一个功能定义两个名称不一样的属性&#xff0c;那么这两个属性彼此互为别名 RequestMapping注解里面的代码 AliasFor("path")String[] value() default {};AliasFor("value")String[] path() default {};G…...

wordpress logy/阿里云免费建站

一、闭包闭包从形式上来说是在外部函数中定义内部函数&#xff0c;并且内部函数引用了外部函数的变量&#xff0c;此变量叫做自由变量。或者说是将组成函数的语句和这些语句的执行环境打包在一起。闭包满足的条件&#xff1a;必须有一个内嵌函数内嵌函数必须使用外部函数的变量…...

如何做网站轮播大图/关键词优化排名软件案例

mongodb由C&#xff0b;&#xff0b;写就&#xff0c;其名字来自humongous这个单词的中间部分&#xff0c;从名字可见其野心所在就是海量数据的处理。关于它的一个最简洁描述为&#xff1a;scalable, high-performance, open source, schema-free, document-oriented database。…...

上海人才招聘官网/南通百度seo代理

简介 YAML 是一种简洁的非标记语言(YAML Ain’t Markup Language),YAML以数据为中心&#xff0c;使用空白&#xff0c;缩进&#xff0c;分行组织数据&#xff0c;从而使得表示更加简洁易读&#xff0c; 常用于作为配置文件, 比json更加简洁。 YAML 1.2 (3rd Edition): http:/…...