如何实现一个基于WebRTC的纯JavaScript点对点通信应用?

来源:站长站作者:狼行天下头衔:草根站长
导读:本期聚焦于小伙伴创作的《如何实现一个基于WebRTC的纯JavaScript点对点通信应用?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何实现一个基于WebRTC的纯JavaScript点对点通信应用?》有用,将其分享出去将是对创作者最好的鼓励。

WebRTC是浏览器内置的实时通信标准,允许两个客户端之间直接建立连接传输音视频、任意数据,无需经过中间服务器转发数据,仅需要信令服务器辅助交换连接信息。下面我们将一步步实现纯JavaScript的WebRTC点对点通信应用。

如何实现一个基于WebRTC的纯JavaScript点对点通信应用?

核心概念说明

在开发前需要先了解几个WebRTC的核心概念:

  • RTCPeerConnection:WebRTC的核心连接对象,负责管理点对点连接的建立、维护和数据传输。
  • 信令服务器:用于两个客户端交换SDP(会话描述协议)和ICE候选信息,本身不参与数据传输,仅做信息中转。
  • ICE候选:用于描述客户端的网络地址信息,包括公网IP、内网IP、端口等,帮助双方找到可连通的网络路径。
  • SDP:描述连接的媒体能力、编码格式等信息,双方需要交换各自的SDP来协商通信参数。

前置准备

我们需要准备一个简单的信令服务器,这里使用Node.js和WebSocket实现,用于两个客户端之间转发SDP和ICE候选信息。首先初始化项目并安装依赖:

mkdir webrtc-demo
cd webrtc-demo
npm init -y
npm install ws

信令服务器实现

信令服务器的逻辑很简单,接收客户端发送的WebSocket消息,然后转发给另一个连接的客户端:

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

// 存储两个连接的客户端
let clients = [];

wss.on('connection', (ws) => {
    clients.push(ws);
    console.log('新客户端连接,当前连接数:', clients.length);

    ws.on('message', (message) => {
        // 把消息转发给另一个客户端
        const otherClient = clients.find(client => client !== ws);
        if (otherClient && otherClient.readyState === WebSocket.OPEN) {
            otherClient.send(message);
        }
    });

    ws.on('close', () => {
        clients = clients.filter(client => client !== ws);
        console.log('客户端断开,当前连接数:', clients.length);
    });
});

console.log('信令服务器启动在 ws://127.0.0.1:8080');

客户端实现

客户端使用纯JavaScript编写,分为连接信令服务器、创建RTCPeerConnection、交换SDP和ICE候选、建立连接几个步骤。

HTML结构

简单的页面结构,包含两个按钮用于发起连接和发送消息,一个输入框输入消息内容,一个区域显示接收的消息:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebRTC点对点通信</title>
</head>
<body>
    <button id="startBtn">发起连接</button>
    <div>
        <input type="text" id="messageInput" placeholder="输入要发送的消息">
        <button id="sendBtn">发送消息</button>
    </div>
    <div id="messageArea"></div>
    <script src="client.js"></script>
</body>
</html>

客户端JavaScript逻辑

client.js的完整实现如下:

// 连接信令服务器
const ws = new WebSocket('ws://127.0.0.1:8080');
// 创建RTCPeerConnection实例,配置STUN服务器用于获取公网地址
const peerConnection = new RTCPeerConnection({
    iceServers: [
        { urls: 'stun:stun.l.google.com:19302' } // 公共STUN服务器
    ]
});
// 用于发送数据的DataChannel
let dataChannel = null;

// 获取页面元素
const startBtn = document.getElementById('startBtn');
const sendBtn = document.getElementById('sendBtn');
const messageInput = document.getElementById('messageInput');
const messageArea = document.getElementById('messageArea');

// 显示消息到页面
function showMessage(text) {
    const p = document.createElement('p');
    p.textContent = text;
    messageArea.appendChild(p);
}

// 处理ICE候选事件,将候选信息通过信令服务器发送给对方
peerConnection.onicecandidate = (event) => {
    if (event.candidate) {
        ws.send(JSON.stringify({
            type: 'ice-candidate',
            candidate: event.candidate
        }));
    }
};

// 处理DataChannel消息接收
peerConnection.ondatachannel = (event) => {
    const receiveChannel = event.channel;
    receiveChannel.onmessage = (e) => {
        showMessage('收到消息:' + e.data);
    };
    receiveChannel.onopen = () => {
        showMessage('数据通道已打开,可以发送消息');
        sendBtn.disabled = false;
    };
};

// WebSocket连接成功
ws.onopen = () => {
    showMessage('信令服务器连接成功');
    startBtn.disabled = false;
};

// 处理接收到的信令消息
ws.onmessage = async (event) => {
    const message = JSON.parse(event.data);
    if (message.type === 'offer') {
        // 收到对方的offer,设置为远程描述,然后创建answer
        await peerConnection.setRemoteDescription(new RTCSessionDescription(message.offer));
        const answer = await peerConnection.createAnswer();
        await peerConnection.setLocalDescription(answer);
        ws.send(JSON.stringify({
            type: 'answer',
            answer: answer
        }));
    } else if (message.type === 'answer') {
        // 收到对方的answer,设置为远程描述
        await peerConnection.setRemoteDescription(new RTCSessionDescription(message.answer));
    } else if (message.type === 'ice-candidate') {
        // 收到对方的ICE候选,添加到连接中
        await peerConnection.addIceCandidate(new RTCIceCandidate(message.candidate));
    }
};

// 发起连接按钮点击事件
startBtn.addEventListener('click', async () => {
    // 创建DataChannel用于传输数据
    dataChannel = peerConnection.createDataChannel('chat');
    dataChannel.onopen = () => {
        showMessage('数据通道已打开,可以发送消息');
        sendBtn.disabled = false;
    };
    dataChannel.onmessage = (e) => {
        showMessage('收到消息:' + e.data);
    };

    // 创建offer
    const offer = await peerConnection.createOffer();
    await peerConnection.setLocalDescription(offer);
    ws.send(JSON.stringify({
        type: 'offer',
        offer: offer
    }));
    showMessage('已发起连接请求,等待对方响应');
    startBtn.disabled = true;
});

// 发送消息按钮点击事件
sendBtn.addEventListener('click', () => {
    const message = messageInput.value.trim();
    if (message && dataChannel && dataChannel.readyState === 'open') {
        dataChannel.send(message);
        showMessage('发送消息:' + message);
        messageInput.value = '';
    }
});

运行测试步骤

按照以下步骤测试应用:

  1. 启动信令服务器:在终端执行node server.js,看到启动成功提示。
  2. 打开两个浏览器窗口,都访问客户端的HTML页面,两个窗口都会连接到信令服务器。
  3. 在其中一个窗口点击发起连接按钮,另一个窗口会自动收到offer并响应answer,双方交换ICE候选后建立连接。
  4. 连接建立后,两个窗口都可以在输入框输入消息,点击发送按钮,对方就能收到消息。

常见问题说明

  • 如果两个客户端在同一内网,可能不需要STUN服务器也能连通,但跨网络场景必须配置STUN或TURN服务器。
  • 信令服务器仅做信息中转,实际数据不会经过服务器,符合WebRTC点对点传输的特性。
  • 如果需要传输音视频,只需要调用getUserMedia获取媒体流,然后通过addTrack方法添加到RTCPeerConnection即可,流程和传输数据类似。
注意:实际生产环境中需要更完善的信令服务器逻辑,处理多用户、断线重连等场景,同时STUN/TURN服务器也需要自己部署或使用可靠的服务。

WebRTCJavaScript点对点通信RTCPeerConnection修改时间:2026-07-08 12:06:39

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。