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

sip开发从理论到实践,让你快速入门sip

目录

引言:

 sip协议是什么?

 sip的网络结构(重点)

 sip的特点

sip使用的url

sip协议的应用领域

sip协议基本的消息类型

请求消息

响应消息

sip协议的消息结构(这个是重点)

sip的常见会话流程(重点)

注册

注销

基于sip协议实现简单的网络视频通话

步骤:

效果:

代码:


  • 引言:

最近,公司让我去了解sip协议,自己花了些的时间去了解了相关的知识,但我发现网上的资料比较乱,没有的对sip协议做一个很好的总结,而且实践很少,对于新手学习sip而言,需要花费大量的时间去找相关的资料,所以我在这里总结一下我自己的学习心得,让大家能花较短的时间也可以对sip协议快速入门。


  •  sip协议是什么?

SIP(Session Initiation Protocol,即初始会话协议)是 IETF 提出的基于文本编码的 IP 电话/多媒体会议协议。用于建立、修改并终止多媒体会话。

SIP 协 议可用于发起会话,也可以用于邀请成员加入已经用其它方式建立的会话。 多媒体会话可以是点到点的话音通信或视频通信,也可以是多点参与的话音 或视频会议等。SIP 协议透明地支持名字映射和重定向服务,便于实现 ISDN, 智能网以及个人移动业务。

SIP 协议可以用多点控制单元(MCU)或全互连的方式代替组播发起多方呼 叫。与 PSTN 相连的 IP 电话网关也可以用 SIP 协议来建立普通电话用户之间 的呼叫。

     

总结:sip协议是一种基于文本编码的协议,用于建立、修改并终止多媒体会话,多使用在IP通话(基于网络来实现通话,类似与微信通话)

扩展知识:ip电话和传统的电话有什么区别呢?如何进行区分呢,分别都是使用了那些协议和技术呢?

区别:ip电话是一个统称,只要是基于互联网来实现实时通话,都可以成为ip电话,想我们生活中的微信通话,qq通话等都是属于ip电话的一种,而基于sip协议来实现的sip话机通话也是IP电话的一种。

区分:在生活中,向我们日常手机那种需要手机卡才能拨打电话的称为传统通话,而只需要有网络就可以拨打电话的就是ip电话了

协议和技术:传统的话机主要是基于PSTN来实现的,使用电路交换技术来传输数据;而qq,微信等是有自己定义的协议来实现,sip话机是基于sip协议来实现,使用分组交换技术传输数据。


  •  sip的网络结构(重点)

sip的网络结构主要有5部分组成

用户代理:SIP 用户代理(UA) 是终端用户设备,如用于创建和管理 SIP 会话的移动电话、多媒体手持设备、PC、PDA 等。用户代理客户机发出消息。用户代理服务器对消息进行响应(常见的用户代理就有sip话机,实现了sip协议的软件换设备(app,网页,其他软件));

代理服务器:用于转发sip请求,作为 User Agent Client 和 User Agent Server 间的中间媒体, 它转发 User Agent Client 来的的邀请,在转发之前,根据被叫标识请求位置 服务器获得被叫的可能位置,然后分别向它们发出邀请;

重定向服务器:接受 User Agent Client 来的邀请,根据被叫标识请求位置服 务器获得被叫的可能位置,把这些信息返回给邀请的发起者(User Agent Client),和 Proxy Server 的不同之处就在于它不转发邀请,邀请由主叫终端 自己完成;

本地服务器和注册服务器:主要用于登记分组终端的当前位置和位置服务的原始数据

如果还需要连接传统的PSTN,则需要添加一个网关,将SIp转化成PSTN信号

sip的网络结构基本组成

在同一个局域网的

 在不同局域网的


  •  sip的特点

协议简单:

SIP协议被设计为非常简单,具有有限的命令集。它也是基于文本的,因此任何人都可以读取在SIP会话中的端点之间传递的SIP消息,SIP协议是一个Client/Sever协议,因此SIP消息分两种:请求消息和响应消息。请求消息是SIP客户端为了激活特定操作而发给服务器端的消息。

可读性强:sip协议是基于文本编码的,在网络中获取后可以直接阅读。所以协议传输的数据可读性强。

扩展性强:sip协议的网络组成是基于分布式部署的,用户可以根据自己的需要部署一台或多台网络组件,如果想连接PSTN网,则可以通过使用id网关来实现异构网的搭建,所以扩展性强。


  • sip使用的url

结构:name@domian

案例:

alice@atlanta.com

bob@biloxi.com

1001@192.168.8.248

1002@192.168.8.248


  • sip协议的应用领域

  

SIP(Session Initiation Protocol)是一种应用层协议,用于建立、修改和终止多媒体会话,如电话呼叫、视频会议等。SIP协议的应用领域包括以下几个方面:

  1. 互联网电话(VoIP):SIP是VoIP中最常用的协议之一,它可以用于建立和管理Internet上的语音通信。通过SIP,用户可以通过互联网进行电话呼叫,无需传统电话线路。

  2. 多媒体会议:SIP可以用于建立和管理多媒体会议,包括音频、视频和文本等形式的通信。通过SIP,多个参与者可以在不同的地理位置之间进行实时的多媒体会话。

  3. 即时消息和在线聊天:SIP可以用于发送即时消息和进行在线聊天。它支持文本消息的传输和处理,并可以实现用户之间的实时通信。

  4. 网络电话交换(Softswitch):SIP可以作为网络电话交换的控制协议,用于连接不同的电话网络和设备。通过SIP,电话呼叫可以在不同的网络之间进行转接和路由。

  5. 增强业务通信:SIP还可以用于增强业务通信,如语音信箱、呼叫转移、呼叫等待等功能。它提供了一种灵活的方式来定制和管理通信服务。

总的来说,SIP协议在VoIP、多媒体会议、即时消息和业务通信等领域都有广泛的应用。它为实现实时通信和多媒体交互提供了一种标准化和可扩展的解决方案。


  • sip协议基本的消息类型

SIP 协议是以层协议的形式组成的,就是说它的行为是以一套相对独立的处理阶段来描述的,每个阶段之间的关系不是很密切。

SIP 协议将 Server 和 User Agent 之间的通讯的消息分为两类:请求消息和响应消息。

  • 请求消息

  • INVITE:表示主叫用户发起会话请求,邀请其他用户加入一个会话。也可以用在呼叫建立后用于更新会话(此时该INVITE又称为Re-invite)。

  • ACK:客户端向服务器端证实它已经收到了对INVITE请求的最终响应。

  • PRACK:表示对1xx响应消息的确认请求消息。

  • BYE:表示终止一个已经建立的呼叫。

  • CANCEL:表示在收到对请求的最终响应之前取消该请求,对于已完成的请求则无影响。

  • REGISTER:表示客户端向SIP服务器端注册列在To字段中的地址信息。

  • OPTIONS:表示查询被叫的相关信息和功能。

  • 以上方法以外,还有其他扩展的方法,如INFO、NOTIFY等等.

响应消息

服务器向客户反馈对应请求的处理结果的 SIP 消息,包括 1xx、2xx、 3xx、4xx、5xx、6xx 响应。

常用的一些响应消息:

  • 100试呼叫(Trying)

  • 180振铃(Ringing)

  • 181呼叫正在前转(Call is Being Forwarded)

  • 200成功响应(OK)

  • 302临时迁移(Moved Temporarily)

  • 400错误请求(Bad Request)

  • 401未授权(Unauthorized)

  • 403禁止(Forbidden)

  • 404用户不存在(Not Found)

  • 408请求超时(Request Timeout)

  • 480暂时无人接听(Temporarily Unavailable)

  • 486线路忙(Busy Here)

  • 504服务器超时(Server Time-out)

  • 600全忙(Busy Everywhere)


  • sip协议的消息结构(这个是重点)

注意:这个看起来很繁琐,感觉不需要记,但实际上在日常开发中,如果需要要抓包去查看信息的话,这个是必须要懂得,每个字段代表什么意思要记下来

请求行:

       请求行分为请求和响应二种类型:

        请求:请求方法         请求路径         协议版本号

         INVITE sip:bob@192.0.2.4 SIP/2.0

         INVITE sip:bob@biloxi.com SIP/2.0

        响应:协议版本号       响应码          原因短语 

        SIP/2.0 100 Trying

        SIP/2.0 180 Ringing


 请求头:


Via: SIP/2.0/UDP pc33.atlanta.com
;branch=z9hG4bKnashds8
Max-Forwards: 70
To: Bob <sip:bob@biloxi.com>
From: Alice <sip:alice@atlanta.com>
;tag= 1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Contact: <sip:alice@pc33.atlanta.com> 
Content-Type: application/sdp
Content-Length: 142


    请求体:

    主要由SDP协议组成

请求类型

 


  • sip的常见会话流程(重点)

注册

 

注销

          

 

                                                        基本得呼叫流程

 

主动呼叫        

 

 

  • 基于sip协议实现简单的网络视频通话

这里是基于sip.js来实现得一个简单得web在线呼叫

步骤:

  1.   从github上下载一个打包号得sip.js文件(这里需要注意,我使用得是15.10版本,然后现在更新到了2.1版了,从1.6版本之后,变化比较大,所以如果要使用我的代码的话,版本不能超过1.6)
  2. 安装一个sip服务器,现在sip.js支持三种类型的服务器,分别是freeswich,onsip,asterisk,他们之间的差别我就不介绍了,现在国内主流的是使用freeswich这个作为sip服务器,本案例就是选用freeswich作为sip服务器
  3. 在运行freeswich服务器后,完成注册就可以实现视频通话了(这里需要注意现在必须要在同一个类型的浏览器才能实现正常的通话)

freeswich的安装教程:Windows下FreeSWITCH的安装及使用_freeswitch管理工具_rivercoder的博客-CSDN博客

效果:

代码:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>sip练习</title>
</head>
<!-- 引入sipjs -->
<script src="./js/sip-0.15.10.js"></script><body><div style="width: 300px;height: 250px;margin: 0 auto;background-color: antiquewhite;
" id="registerDiv"></form><p align="center"><tr><td>用户名:<input type="text" name="username" id="username" value="" placeholder="请输入sip账号"></td></tr><br /><tr><td>密 &nbsp;&nbsp;码:<input type="password" id="password" name="password" value="" placeholder="请输入密码"></td></tr><br /></p><p align="center"><td><input type="submit" name="register" value="register" id="register" "></td></p><form></div><div style="width: 500px;height: 450px;margin: 0 auto;background-color: antiquewhite;" id="mainDiv"><audio id="ringtone" loop src="./sounds/ringtone.wav"></audio> <!--//来电提示音--><audio id="ringbacktone" loop src="./sounds/ringbacktone.wav"></audio> <!--//电话呼叫后声音--><audio id="dtmfTone" src="./sounds/dtmf.wav"></audio></form><p align="center"><tr><td>账号:<input type="text" name="username" id="number" value="" placeholder="请输入sip账号"></td></tr><br /><tr><td>消息:<input type="text" id="msg" name="msg" value="hello" placeholder="要发送的消息"></td></tr><br /></p><button id="startCall">Start Call</button><button id="endCall">End Call</button><button id="transfer">transfer</button><button id="hold">hold</button><button id="unhold">unhold</button><button id="mute">mute</button><button id="unmute">unmute</button><button id="sendMessage">Send Message</button><form><div style="width: 90%; height: 100%;background-color: #f6f2f2; border: 2px solid blue; padding:0px; margin-top: 4px;"><video id="remoteView" style="width: 200px; height: 200px; background-color: #c5e5cd; margin-left: 20px;" autoplay></video><video id="localVideo" autoplay="autoplay" muted="muted"style="width: 200px; height: 200px; background-color: #d8d0d0; margin-left: 20px;"></video></div></div><script>var ua;//初始化按钮变量 var sessionall;var startCall = document.getElementById('startCall');var endCall = document.getElementById('endCall');var transfer = document.getElementById('transfer');var hold = document.getElementById('hold');var unhold = document.getElementById('unhold');var sendMessage = document.getElementById('sendMessage');var mute = document.getElementById('mute');var unmute = document.getElementById('unmute');var remoteView = document.getElementById('remoteView');var localVideo = document.getElementById('localVideo');var currentSession=null;        //当前会话<!--  实现注册功能 -->var test =document.getElementById("register").addEventListener('click', function (e) {var username = document.getElementById("username").value; var password = document.getElementById("password").value; //定义一个config var configuration={ uri: 'sip:' +username + '@192.168.8.248:5060',displayName: username, password: password, transportOptions: {//freeswich会运行websocket服务器,一个是ws类型,端口对应5066,用于本地测试,一个是wss类型,端口对应7443,用于实际开发,相当于加入了ssl的wswsServers: ['ws://192.168.8.248:5066']},register: true // 启用注册功能 }; //开始注册sip ua=new SIP.UA(configuration); //登录成功后进行回调ua.on('registered', function () {alert('登录成功'); document.getElementById("registerDiv").style.display = "none";document.getElementById("mainDiv").style.display="block";});		// 接听来电ua.on('invite', function (session) {// 开始振铃Ring.startRingTone();var url = session.remoteIdentity.uri.toString() + "来电了,是否接听";//弹出是否接听对话框var isaccept = confirm(url);if (isaccept) {//接受来电session.accept({sessionDescriptionHandlerOptions: {constraints: {audio: true,video: true}}});session.on("terminated", function (message, cause) {Ring.stopRingTone();})/****/session.on('accepted', function (response, cause) {console.error(response);console.error(session);Ring.stopRingTone();// If there is a video track, it will attach the video and audio to the same element//// Gets remote tracksvar pc = session.sessionDescriptionHandler.peerConnection;var x=pc.getReceivers();if(pc.getReceivers()){var remoteStream = new MediaStream();//接听会话pc.getReceivers().forEach(function (receiver) {remoteStream.addTrack(receiver.track);});remoteView.srcObject = remoteStream;remoteView.play();}var y=pc.getSenders();//发起会话if (pc.getSenders()) {var localStream = new MediaStream();pc.getSenders().forEach(function (sender) {localStream.addTrack(sender.track);});localVideo.srcObject = localStream;localVideo.play();}})session.on('bye', function (resp, cause) {Ring.stopRingTone();});}else {//拒绝来电session.reject();}}); //接听会话结束}, false); // 页面加载时调用window.onload = function () {document.getElementById("mainDiv").style.display = "none"; };/***  绑定方法* @param obj 要绑定事件的元素* @param ev 绑定的事件* @param fn  绑定事件的函数*/function bindEvent(obj, ev, fn) {if (obj.attachEvent) {obj.attachEvent("on" + ev, fn);}else {obj.addEventListener(ev, fn, false);}}//发送消息bindEvent(sendMessage, 'click', function () {// Sends a new messagevar number = document.getElementById("number").value;var src=number+"@192.168.8.248"var message = document.getElementById("msg").value;ua.message(src, message);// When receiving a message, prints it outua.on('message', function (message) {console.log(message.body);});})/*** 拨打电话*/bindEvent(startCall, 'click', function () {var number = document.getElementById("number").value;var sippath=number+ "@192.168.8.248";//创建一个新的出站(用户代理客户端)会话currentSession = ua.invite(number, {sessionDescriptionHandlerOptions: {constraints: {audio: true,video: true},alwaysAcquireMediaFirst: true // 此参数是sip.js官方修复在firefox遇到的bug所设置}});//开始嘟嘟嘟Ring.startRingbackTone();//每次收到成功的最终(200-299)响应时都会触发。currentSession.on("accepted", function (response, cause) {console.log(response);Ring.stopRingbackTone();//获取seesion// Gets remote tracksvar pc = currentSession.sessionDescriptionHandler.peerConnection;//接听会话if(pc.getReceivers()){var remoteStream = new MediaStream();pc.getReceivers().forEach(function (receiver) {remoteStream.addTrack(receiver.track);});remoteView.srcObject = remoteStream;remoteView.play();}//发起会话if (pc.getSenders()) {var localStream = new MediaStream();pc.getSenders().forEach(function (sender) {localStream.addTrack(sender.track);});localVideo.srcObject = localStream;localVideo.play();}})//挂机时会触发currentSession.on("bye", function (response, cause) {Ring.stopRingbackTone();console.log(response);})//请求失败时触发,无论是由于最终响应失败,还是由于超时,传输或其他错误。currentSession.on("failed", function (response, cause) {Ring.stopRingbackTone();console.log(response);})/****/currentSession.on("terminated", function (message, cause) {Ring.stopRingbackTone();})/*** 对方拒绝*/currentSession.on('rejected', function (response, cause) {Ring.stopRingbackTone();})})//振铃  var Ring = {/*** 振铃*/startRingTone: function () {let play = document.getElementById("ringtone").play();play.then(() => {}).catch((err) => {});},/*** 停止振铃*/stopRingTone: function () {document.getElementById("ringtone").pause();},startRingbackTone: function () {let play = document.getElementById("ringbacktone").play();play.then(() => {}).catch((err) => {});},stopRingbackTone: function () {document.getElementById("ringbacktone").pause();}};</script></body></html>

相关文章:

sip开发从理论到实践,让你快速入门sip

目录 引言&#xff1a; sip协议是什么&#xff1f; sip的网络结构&#xff08;重点&#xff09; sip的特点 sip使用的url sip协议的应用领域 sip协议基本的消息类型 请求消息 响应消息 sip协议的消息结构&#xff08;这个是重点&#xff09; sip的常见会话流程&#xf…...

十三、Linux中必须知道的几个快捷键!!!

1、强制停止 当某些代码正在运行时&#xff0c;你想让其停止&#xff0c;只需要按下如下快捷键即可&#xff1a; 【CTRL】【C】 示例&#xff1a; 2、退出 Linux系统自带python3解释器&#xff0c;当你进入python3解释器之后&#xff0c;需要退出时&#xff0c;只需要按下&am…...

Django进阶-文件上传

普通文件上传 定义 用户可以通过浏览器将图片等文件上传到网站 场景 用户上传头像 上传流动性的文档【pdf&#xff0c;txt】等 上传规范-后端 1.视图函数中&#xff0c;用request。FILES取文件框的内容 file request.FILES[xxx] 说明&#xff1a; 1.FILES的key对应页面中…...

clickhouse-数据导入导出方案

一、简介 clickhouse有多种数据的导入导出方式&#xff0c;可以灵活使用&#xff0c;下面对这些方式分别做些介绍&#xff0c;导入导出的写法与格式和格式设置有关。 二、导入 1.从s3导入 详情可查看官网&#xff0c;也可以在这里获取数据集 -- 建库建表 CREATE DATABASE …...

[JavaWeb]【一】入门JavaWeb开发总概及HTML、CSS、JavaScript

目录 一 特色 二 收获​编辑 三 什么是web? 四 网站的工作流程 五 web网站的开发模式​编辑 六 web开发课程学习安排 七、初始web前端 八 HTML、CSS 8.1 什么是HTNL\CSS(w3cschool) 8.2 HTML快速入门 8.3 VS Code开发工具 8.3.1 插件 8.3.2 主题&#xff08;改变颜色&…...

Python自动化小技巧18——自动化资产月报(word设置字体表格样式,查找替换文字)

案例背景 每月都要写各种月报&#xff0c;经营管理月报&#xff0c;资产月报.....这些报告文字目标都是高度相似的&#xff0c;只是需要替换为每个月的实际数据就行&#xff0c;如下&#xff1a; (打码是怕信息泄露.....) 可以看到&#xff0c;这个报告的都是高度模板化&…...

FFmpeg5.0源码阅读——VideoToobox硬件解码

摘要&#xff1a;本文描述了FFmpeg中videotoobox解码器如何进行解码工作&#xff0c;如何将一个编码的码流解码为最终的裸流。   关键字&#xff1a;videotoobox,decoder,ffmpeg   VideoToolbox 是一个低级框架&#xff0c;提供对硬件编码器和解码器的直接访问。 它提供视频…...

IDEA 中Tomcat源码环境搭建

一、从仓库中拉取源代码 配置仓库地址、项目目录&#xff1b;点击Clone按钮&#xff0c;从仓库中拉取代码 Tomcat源码对应的github地址&#xff1a; https://github.com/apache/tomcat.git 二、安装Ant插件 打开 File -> Setting -> Plugins 三、添加Build文件 &…...

MATLAB | 七夕节用MATLAB画个玫瑰花束叭

Hey又是一年七夕节要到了&#xff0c;每年一次直男审美MATLAB绘图大赛开始hiahiahia&#xff0c;真的这些代码越写越不知道咋写&#xff0c;又不想每年把之前的代码翻出来再发一遍&#xff0c;于是今年又对我之前写的老代码进行了点优化组合&#xff0c;整了个花球变花束&#…...

嵌入式开发之configure

1 前述 在Linux的应用或者驱动开发过程中&#xff0c;编写makefile是无法避免的问题&#xff0c;但是由于makefile的各种规则&#xff0c;或显式&#xff0c;或隐式&#xff0c;非常多&#xff0c;不经常写的话&#xff0c;很难写出一个可用的makefile文件。为了“偷懒”&…...

深入浅出Pytorch函数——torch.nn.Module

分类目录&#xff1a;《深入浅出Pytorch函数》总目录 Pytorch中所有网络的基类&#xff0c;我们的模型也应该继承这个类。Modules也可以包含其它Modules,允许使用树结构嵌入他们&#xff0c;我们还可以将子模块赋值给模型属性。 语法 torch.nn.Module(*args, **kwargs)方法 …...

【100天精通python】Day38:GUI界面编程_PyQt 从入门到实战(中)_数据库操作与多线程编程

目录 专栏导读 4 数据库操作 4.1 连接数据库 4.2 执行 SQL 查询和更新&#xff1a; 4.3 使用模型和视图显示数据 5 多线程编程 5.1 多线程编程的概念和优势 5.2 在 PyQt 中使用多线程 5.3 处理多线程间的同步和通信问题 5.3.1 信号槽机制 5.3.2 线程安全的数据访问 Q…...

STM32--TIM定时器(3)

文章目录 输入捕获简介频率测量输入捕获通道输入捕获基本结构PWMI的基本结构输入捕获模式测量PWM频率和占空比代码 编码器接口正交编码器工作模式接口基本结构TIM编码接口器测速代码&#xff1a; 输入捕获简介 输入捕获IC(Input Capture)&#xff0c;是处理器捕获外部输入信号…...

爬虫框架- feapder + 爬虫管理系统 - feaplat 的学习简记

文章目录 feapder 的使用feaplat 爬虫管理系统部署 feapder 的使用 feapder是一款上手简单&#xff0c;功能强大的Python爬虫框架 feapder 官方文档 文档写的很详细&#xff0c;可以直接上手。 基本命令&#xff1a; 创建爬虫项目 feapder create -p first-project创建爬虫 …...

设计模式详解-享元模式

类型&#xff1a;结构型模式 实现原理&#xff1a;尝试重用现有的同类对象&#xff0c;如果未找到匹配的对象&#xff0c;则创建新对象 目的&#xff1a;减少创建对象的数量以减少内存占用和提高性能。 解决的问题&#xff1a;大量的对象可能造成的内存溢出问题 解决方法&a…...

BDA初级分析——用SQL筛选数据

一、用SQL对数据分组 GROUP BY Group by&#xff0c;按...分组 作用:根据给定字段进行字段的分组&#xff0c;通常和聚合函数配合使用&#xff0c;实现分组的分析 写法:select ...from ...group by 字段名 (也可以是多个字段) GROUP BY的逻辑 SELECT gender,COUNT(user_id) …...

(成功踩坑)electron-builder打包过程中报错

目录 注意&#xff1a;文中的解决方法2&#xff0c;一定全部看完&#xff0c;再进行操作&#xff0c;有坑 背景 报错1&#xff1a; 报错2&#xff1a; 1.原因&#xff1a;网络连接失败 2.解决方法1&#xff1a; 3.解决方法2&#xff1a; 3.1查看缺少什么资源文件 3.2去淘…...

【STM32】 工程

&#x1f6a9; WRITE IN FRONT &#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四" &#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2022博客之星TO…...

Git概述

目录 一、什么是Git 二、什么是版本控制系统 三、Git和SVN对比 SVN集中式 SVN优缺点 Git分布式 Git优缺点 四、Git工作流程 四个工作区域 工作流程 五、Git下载与安装 一、什么是Git 很多人都知道&#xff0c;林纳斯托瓦兹在1991年创建了开源的Linux&#xff0c;从…...

ubuntu 编译安装nginx及安装nginx_upstream_check_module模块

如果有帮助到你&#xff0c;麻烦点个赞呗&#xff5e; 一、下载安装包 # 下载nginx_upstream_check_module模块 wget https://codeload.github.com/yaoweibin/nginx_upstream_check_module/zip/master# 解压 unzip master# 下载nginx 1.21.6 wget https://github.com/nginx/…...

低代码拖拽逻辑执行慢10倍?:用3个内存布局优化+1个opcode精简表,让RuleEngine吞吐量突破23,000 TPS

第一章&#xff1a;低代码拖拽逻辑执行慢10倍&#xff1f;&#xff1a;用3个内存布局优化1个opcode精简表&#xff0c;让RuleEngine吞吐量突破23,000 TPS低代码规则引擎在拖拽式策略编排场景下&#xff0c;常因对象频繁分配、字段间接寻址与冗余指令解析导致执行路径膨胀。我们…...

Ostrakon-VL-8B实战:利用Git进行多模态模型版本管理与协作开发

Ostrakon-VL-8B实战&#xff1a;利用Git进行多模态模型版本管理与协作开发 在餐饮AI项目的开发过程中&#xff0c;我们常常会遇到这样的场景&#xff1a;数据科学家调整了Ostrakon-VL-8B的微调参数&#xff0c;工程师更新了模型推理的接口代码&#xff0c;产品经理则迭代了用于…...

【RK3588 NPU性能调优实战】多线程异步推理YOLOv5,榨干6TOPS算力

1. 为什么你的RK3588 NPU跑不满6TOPS&#xff1f; 第一次在RK3588上跑YOLOv5时&#xff0c;我也被官方宣称的6TOPS算力唬住了。直到亲眼看到npu-smi显示的实际利用率——好家伙&#xff0c;不到30%&#xff01;这就像买了辆跑车却只能挂一档开。经过两周的折腾&#xff0c;终于…...

Phi-3-mini-128k-instruct与STM32开发:生成嵌入式C代码与调试逻辑

Phi-3-mini-128k-instruct与STM32开发&#xff1a;生成嵌入式C代码与调试逻辑 1. 引言 如果你玩过STM32&#xff0c;尤其是像STM32F103C8T6这种经典的“蓝色药丸”最小系统板&#xff0c;肯定对下面这些场景不陌生&#xff1a;为了点亮一个LED&#xff0c;翻遍数据手册&#…...

AIVideo效果展示:输入主题输出专业视频,惊艳案例分享

AIVideo效果展示&#xff1a;输入主题输出专业视频&#xff0c;惊艳案例分享 1. 专业级视频生成效果概览 AIVideo一站式AI长视频工具能够将简单的文字主题转化为完整的专业视频作品。只需输入一个主题&#xff0c;系统就会自动完成从文案创作、分镜设计、画面生成到配音剪辑的…...

终极指南:如何让Nautilus、Dolphin等Linux文件管理器拥有macOS Finder般流畅的快捷键体验

终极指南&#xff1a;如何让Nautilus、Dolphin等Linux文件管理器拥有macOS Finder般流畅的快捷键体验 【免费下载链接】kinto Mac-style shortcut keys for Linux & Windows. 项目地址: https://gitcode.com/gh_mirrors/kin/kinto 你是否厌倦了在Linux文件管理器中不…...

降AIGC哪家强?2026零成本保姆级教程:DeepSeek/Kimi/豆包专属降重指令实测与差异解析

很多时候大学生写论文逻辑太严谨、话术太规范&#xff0c;反而会导致AI率过高&#xff0c;且一旦AI率过高&#xff0c;轻则退回重改&#xff0c;重则取消答辩资格&#xff0c;这后果谁都担不起。 为了帮大家有效降低aigc率&#xff0c;这周我专门针对目前市面上最主流的三款大…...

华硕笔记本终极电池拯救指南:用G-Helper实现智能充电与健康修复

华硕笔记本终极电池拯救指南&#xff1a;用G-Helper实现智能充电与健康修复 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops. Control tool for ROG Zephyrus G14, G15, G16, M16, Flow X13, Flow X16, TUF, Strix, Scar and other models …...

PdgCntEditor三步搞定PDF书签目录自动生成

1. 为什么你需要PDF书签目录&#xff1f; 每次打开几百页的PDF文档&#xff0c;像无头苍蝇一样滑动滚动条找内容&#xff1f;这种体验我太懂了。上周处理一份300多页的技术手册&#xff0c;光是翻目录就花了半小时&#xff0c;直到我发现PdgCntEditor这个神器。它能把杂乱无章…...

推荐一款微服务商城系统:技术栈新、全开源、好二开、运维还省心

一个开源商城&#xff0c;最怕的是什么&#xff1f;不是功能少&#xff0c;功能少可以慢慢加。不是文档烂&#xff0c;文档烂可以慢慢啃。最怕的是&#xff1a;你把系统拿到手&#xff0c;折腾了半天终于跑起来&#xff0c;结果发现核心代码是加密的&#xff0c;想改个支付逻辑…...