ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] > [参考](https://a-wing.github.io/webrtc-book-cn/04_the-need-for-a-signaling-channel.html#%E5%BB%BA%E7%AB%8B%E7%AE%80%E5%8D%95%E7%9A%84%E5%91%BC%E5%8F%AB%E6%B5%81%E7%A8%8B) ## 概述 描述涉及两个客户端和一个服务器的非常简单的 JavaScript 应用程序的设计和实现 ![](https://a-wing.github.io/webrtc-book-cn/assets/img/rcwr_0401.c20e3708.png) 1. 通道发起方,例如对等方,它首先主动与远端建立专用的通信通道 2. 信令服务器,管理通道创建并充当消息中继节点 3. 频道加入者,例如,远程方加入已存在的频道 ## 实力 ``` npm install socket.io npm install node-static ``` <details> <summary>index.html</summary> ``` <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>WebRTC client</title> </head> <body> <script src="/socket.io/socket.io.js"></script> <div id="scratchPad"></div> <script type="application/javascript" language="JavaScript"> // Get <div> placeholder element from DOM div = document.getElementById('scratchPad'); // Connect to server var socket = io.connect('localhost:8181'); // Ask channel name from user channel = prompt("Enter signaling channel name:"); if (channel !== "") { console.log('Trying to create or join channel: ', channel); // Send 'create or join' to the server socket.emit('create or join', channel); } // Handle 'created' message socket.on('created', function (channel) { console.log('channel ' + channel + ' has been created!'); console.log('This peer is the initiator...'); // Dynamically modify the HTML5 page div.insertAdjacentHTML( 'beforeEnd', '<p>Time: ' +(performance.now() / 1000).toFixed(3) + ' --> Channel '+ channel + ' has been created! </p>'); div.insertAdjacentHTML( 'beforeEnd', '<p>Time: ' +(performance.now() / 1000).toFixed(3) +' --> This peer is the initiator...</p>'); }); // Handle 'full' message socket.on('full', function (channel) { console.log('channel ' + channel + ' is too crowded! Cannot allow you to enter, sorry :-('); div.insertAdjacentHTML( 'beforeEnd', '<p>Time: ' +(performance.now() / 1000).toFixed(3) + ' --> channel ' + channel + ' is too crowded! Cannot allow you to enter, sorry :-( </p>'); }); // Handle 'remotePeerJoining' message socket.on('remotePeerJoining', function (channel) { console.log('Request to join ' + channel); console.log('You are the initiator!'); div.insertAdjacentHTML( 'beforeEnd', '<p style="color:red">Time: ' +(performance.now() / 1000).toFixed(3) +' --> Message from server: request to join channel ' +channel + '</p>'); }); // Handle 'joined' message socket.on('joined', function (msg) { console.log('Message from server: ' + msg); div.insertAdjacentHTML( 'beforeEnd', '<p>Time: ' +(performance.now() / 1000).toFixed(3) +' --> Message from server: </p>'); div.insertAdjacentHTML( 'beforeEnd', '<p style="color:blue">' +msg + '</p>'); div.insertAdjacentHTML( 'beforeEnd', '<p>Time: ' +(performance.now() / 1000).toFixed(3) +' --> Message from server: </p>'); div.insertAdjacentHTML( 'beforeEnd', '<p style="color:blue">' +msg + '</p>'); }); // Handle 'broadcast: joined' message socket.on('broadcast: joined', function (msg) { div.insertAdjacentHTML( 'beforeEnd', '<p style="color:red">Time: ' +(performance.now() / 1000).toFixed(3) +' --> Broadcast message from server: </p>'); div.insertAdjacentHTML( 'beforeEnd', '<p style="color:red">' +msg + '</p>'); console.log('Broadcast message from server: ' + msg); // Start chatting with remote peer: // 1. Get user's message var myMessage = prompt('Insert message to be sent to your peer:', ""); // 2. Send to remote peer (through server) socket.emit('message', { channel: channel, message: myMessage }); }); // Handle remote logging message from server socket.on('log', function (array) { console.log.apply(console, array); }); // Handle 'message' message socket.on('message', function (message) { console.log('Got message from other peer: ' + message); div.insertAdjacentHTML( 'beforeEnd', '<p>Time: ' +(performance.now() / 1000).toFixed(3) +' --> Got message from other peer: </p>'); div.insertAdjacentHTML( 'beforeEnd', '<p style="color:blue">' +message + '</p>'); // Send back response message: // 1. Get response from user var myResponse = prompt('Send response to other peer:', ""); // 2. Send it to remote peer (through server) socket.emit('response', { channel: channel, message: myResponse }); }); // Handle 'response' message socket.on('response', function (response) { console.log('Got response from other peer: ' + response); div.insertAdjacentHTML( 'beforeEnd', '<p>Time: ' +(performance.now() / 1000).toFixed(3) +' --> Got response from other peer: </p>'); div.insertAdjacentHTML( 'beforeEnd', '<p style="color:blue">' +response + '</p>'); // Keep on chatting var chatMessage = prompt('Keep on chatting. Write "Bye" to quit conversation', ""); // User wants to quit conversation: send 'Bye' to remote party if(chatMessage == "Bye") { div.insertAdjacentHTML( 'beforeEnd', '<p>Time: ' +(performance.now() / 1000).toFixed(3) +' --> Sending "Bye" to server...</p>'); console.log('Sending "Bye" to server'); socket.emit('Bye', channel); div.insertAdjacentHTML( 'beforeEnd', '<p>Time: ' +(performance.now() / 1000).toFixed(3) +' --> Going to disconnect...</p>'); console.log('Going to disconnect...'); // Disconnect from server socket.disconnect(); } else { // Keep on going: send response back // to remote party (through server) socket.emit('response', { channel: channel, message: chatMessage }); } }); // Handle 'Bye' message socket.on('Bye', function () { console.log('Got "Bye" from other peer! Going to disconnect...'); div.insertAdjacentHTML( 'beforeEnd', '<p>Time: ' +(performance.now() / 1000).toFixed(3) +' --> Got "Bye" from other peer!</p>'); div.insertAdjacentHTML( 'beforeEnd', '<p>Time: ' +(performance.now() / 1000).toFixed(3) +' --> Sending "Ack" to server</p>'); // Send 'Ack' back to remote party (through server) console.log('Sending "Ack" to server'); socket.emit('Ack'); // Disconnect from server div.insertAdjacentHTML( 'beforeEnd', '<p>Time: ' +(performance.now() / 1000).toFixed(3) +' --> Going to disconnect...</p>'); console.log('Going to disconnect...'); socket.disconnect(); }); </script> </body> </html> ``` </details> <br /> <details> <summary>NodeSocketIoServer.js</summary> ``` const static = require('node-static'); const http = require('http'); // 创建一个文件服务 const file = new(static.Server)(); // We use the http module’s createServer function and // use our instance of node-static to serve the files const app = http.createServer(function (req, res) { file.serve(req, res); }).listen(8181); // Use socket.io JavaScript library for real-time web applications const io = require('socket.io').listen(app); // Let's start managing connections... io.sockets.on('connection', function (socket) { // Handle 'message' messages socket.on('message', function (message) { log('S --> Got message: ', message); socket.broadcast.to(message.channel).emit('message', message.message); }); /** 1.验证所提及的渠道是一个全新的通道(即其中没有客户) 2.将服务器端 room 与通道关联 3.允许发出请求的客户端加入通道 4.向客户端发送一条名为 created 的通知消息 */ socket.on('create or join', function (channel) { const numClients = io.of('/').in(channel).clients.length console.log('numclients = ' + numClients); console.log(channel); console.log(io.sockets.adapter.rooms[channel]); // First client joining... if (numClients === 0) { socket.join(channel); socket.emit('created', channel); // Second client joining... } else if (numClients === 1) { // Inform initiator... io.sockets.in(channel).emit('remotePeerJoining', channel); // Let the new peer join channel socket.join(channel); socket.broadcast.to(channel).emit('broadcast: joined', 'S --> broadcast(): client ' + socket.id + ' joined channel ' + channel); } else { // max two clients console.log("Channel full!"); socket.emit('full', channel); } }); // Handle 'response' messages socket.on('response', function (response) { log('S --> Got response: ', response); // Just forward message to the other peer socket.broadcast.to(response.channel).emit('response', response.message); }); // Handle 'Bye' messages socket.on('Bye', function(channel){ // Notify other peer socket.broadcast.to(channel).emit('Bye'); // Close socket from server's side socket.disconnect(); }); // Handle 'Ack' messages socket.on('Ack', function () { console.log('Got an Ack!'); // Close socket from server's side socket.disconnect(); }); // Utility function used for remote logging function log() { let array = [">>> "]; for (let i = 0; i < arguments.length; i++) { array.push(arguments[i]); } socket.emit('log', array); } }); ``` </details> <br /> 访问`http://127.0.0.1:8181/`