{"id":65157,"date":"2026-01-24T15:40:44","date_gmt":"2026-01-24T07:40:44","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/65157.html"},"modified":"2026-01-24T15:40:44","modified_gmt":"2026-01-24T07:40:44","slug":"%e6%9e%84%e5%bb%ba%e8%87%aa%e5%b7%b1%e7%9a%84-webrtc-%e4%bf%a1%e4%bb%a4%e6%9c%8d%e5%8a%a1%e5%99%a8-node-js-%e5%ae%9e%e6%88%98","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/65157.html","title":{"rendered":"\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218)"},"content":{"rendered":"<h2>\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218)<\/h2>\n<p>\u672c\u6587\u662f WebRTC \u7cfb\u5217\u4e13\u680f\u7684\u7b2c\u4e8c\u5341\u4e00\u7bc7,\u5c06\u624b\u628a\u624b\u6559\u4f60\u4f7f\u7528 Node.js \u6784\u5efa\u4e00\u4e2a\u5b8c\u6574\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668,\u5305\u62ec WebSocket \u901a\u4fe1\u3001\u623f\u95f4\u7ba1\u7406\u548c Offer\/Answer \u4ea4\u6362\u3002<\/p>\n<hr \/>\n<h3>\u76ee\u5f55<\/h3>\n<li>\u4fe1\u4ee4\u670d\u52a1\u5668\u6982\u8ff0<\/li>\n<li>\u9879\u76ee\u7ed3\u6784<\/li>\n<li>WebSocket \u670d\u52a1\u5668<\/li>\n<li>\u623f\u95f4\u7ba1\u7406<\/li>\n<li>\u4fe1\u4ee4\u6d88\u606f\u5904\u7406<\/li>\n<li>\u5ba2\u6237\u7aef\u5b9e\u73b0<\/li>\n<li>\u5b8c\u6574\u4ee3\u7801<\/li>\n<li>\u90e8\u7f72\u4e0e\u6d4b\u8bd5<\/li>\n<li>\u603b\u7ed3<\/li>\n<hr \/>\n<h3>1. \u4fe1\u4ee4\u670d\u52a1\u5668\u6982\u8ff0<\/h3>\n<h4>1.1 \u4fe1\u4ee4\u670d\u52a1\u5668\u7684\u4f5c\u7528<\/h4>\n<p>\u4fe1\u4ee4\u670d\u52a1\u5668\u804c\u8d23:<\/p>\n<p>1. \u7528\u6237\u7ba1\u7406<br \/>\n   &#8211; \u7528\u6237\u8fde\u63a5\/\u65ad\u5f00<br \/>\n   &#8211; \u7528\u6237\u8eab\u4efd\u6807\u8bc6<\/p>\n<p>2. \u623f\u95f4\u7ba1\u7406<br \/>\n   &#8211; \u521b\u5efa\/\u52a0\u5165\/\u79bb\u5f00\u623f\u95f4<br \/>\n   &#8211; \u623f\u95f4\u6210\u5458\u5217\u8868<\/p>\n<p>3. \u6d88\u606f\u8f6c\u53d1<br \/>\n   &#8211; SDP Offer\/Answer<br \/>\n   &#8211; ICE Candidate<br \/>\n   &#8211; \u81ea\u5b9a\u4e49\u6d88\u606f<\/p>\n<p>4. \u72b6\u6001\u540c\u6b65<br \/>\n   &#8211; \u7528\u6237\u72b6\u6001<br \/>\n   &#8211; \u623f\u95f4\u72b6\u6001<\/p>\n<h4>1.2 \u4fe1\u4ee4\u6d41\u7a0b<\/h4>\n<p>\u5b8c\u6574\u4fe1\u4ee4\u6d41\u7a0b:<\/p>\n<p>\u7528\u6237 A                  \u4fe1\u4ee4\u670d\u52a1\u5668                  \u7528\u6237 B<br \/>\n  |                         |                         |<br \/>\n  |  1. \u8fde\u63a5 WebSocket      |                         |<br \/>\n  | &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&gt; |                         |<br \/>\n  |                         |                         |<br \/>\n  |  2. \u52a0\u5165\u623f\u95f4 &#034;room1&#034;    |                         |<br \/>\n  | &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&gt; |                         |<br \/>\n  |                         |                         |<br \/>\n  |                         |  3. \u8fde\u63a5 WebSocket      |<br \/>\n  |                         | &lt;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- |<br \/>\n  |                         |                         |<br \/>\n  |                         |  4. \u52a0\u5165\u623f\u95f4 &#034;room1&#034;    |<br \/>\n  |                         | &lt;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- |<br \/>\n  |                         |                         |<br \/>\n  |  5. \u901a\u77e5: B \u52a0\u5165        |                         |<br \/>\n  | &lt;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- |                         |<br \/>\n  |                         |                         |<br \/>\n  |  6. \u53d1\u9001 Offer \u7ed9 B     |                         |<br \/>\n  | &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&gt; |                         |<br \/>\n  |                         |  7. \u8f6c\u53d1 Offer          |<br \/>\n  |                         | &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&gt; |<br \/>\n  |                         |                         |<br \/>\n  |                         |  8. \u53d1\u9001 Answer         |<br \/>\n  |                         | &lt;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- |<br \/>\n  |  9. \u8f6c\u53d1 Answer         |                         |<br \/>\n  | &lt;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- |                         |<br \/>\n  |                         |                         |<br \/>\n  |  10. ICE Candidate \u4ea4\u6362 (\u53cc\u5411)                    |<br \/>\n  | &lt;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&gt;  |<br \/>\n  |                         |                         |<\/p>\n<h4>1.3 \u6280\u672f\u9009\u578b<\/h4>\n<table>\n<tr>\u6280\u672f\u9009\u62e9\u539f\u56e0<\/tr>\n<tbody>\n<tr>\n<td>\u8fd0\u884c\u65f6<\/td>\n<td>Node.js<\/td>\n<td>\u5f02\u6b65 I\/O,\u9002\u5408\u5b9e\u65f6\u5e94\u7528<\/td>\n<\/tr>\n<tr>\n<td>WebSocket<\/td>\n<td>ws<\/td>\n<td>\u8f7b\u91cf,\u6027\u80fd\u597d<\/td>\n<\/tr>\n<tr>\n<td>HTTP<\/td>\n<td>Express<\/td>\n<td>\u53ef\u9009,\u63d0\u4f9b REST API<\/td>\n<\/tr>\n<tr>\n<td>\u6570\u636e\u5b58\u50a8<\/td>\n<td>\u5185\u5b58\/Redis<\/td>\n<td>\u7b80\u5355\u573a\u666f\u7528\u5185\u5b58<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h3>2. \u9879\u76ee\u7ed3\u6784<\/h3>\n<h4>2.1 \u76ee\u5f55\u7ed3\u6784<\/h4>\n<p>signaling-server\/<br \/>\n\u251c\u2500\u2500 package.json<br \/>\n\u251c\u2500\u2500 server.js              # \u4e3b\u5165\u53e3<br \/>\n\u251c\u2500\u2500 src\/<br \/>\n\u2502   \u251c\u2500\u2500 SignalingServer.js # \u4fe1\u4ee4\u670d\u52a1\u5668\u7c7b<br \/>\n\u2502   \u251c\u2500\u2500 RoomManager.js     # \u623f\u95f4\u7ba1\u7406<br \/>\n\u2502   \u251c\u2500\u2500 MessageHandler.js  # \u6d88\u606f\u5904\u7406<br \/>\n\u2502   \u2514\u2500\u2500 utils.js           # \u5de5\u5177\u51fd\u6570<br \/>\n\u251c\u2500\u2500 client\/<br \/>\n\u2502   \u251c\u2500\u2500 index.html         # \u5ba2\u6237\u7aef\u9875\u9762<br \/>\n\u2502   \u251c\u2500\u2500 app.js             # \u5ba2\u6237\u7aef\u903b\u8f91<br \/>\n\u2502   \u2514\u2500\u2500 style.css          # \u6837\u5f0f<br \/>\n\u2514\u2500\u2500 README.md<\/p>\n<h4>2.2 package.json<\/h4>\n<p><span class=\"token punctuation\">{<\/span><br \/>\n  <span class=\"token string-property property\">&#034;name&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;webrtc-signaling-server&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;version&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;1.0.0&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;description&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;WebRTC Signaling Server&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;main&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;server.js&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;scripts&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token string-property property\">&#034;start&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;node server.js&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token string-property property\">&#034;dev&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;nodemon server.js&#034;<\/span><br \/>\n  <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;dependencies&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token string-property property\">&#034;ws&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;^8.14.2&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token string-property property\">&#034;uuid&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;^9.0.0&#034;<\/span><br \/>\n  <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n  <span class=\"token string-property property\">&#034;devDependencies&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token string-property property\">&#034;nodemon&#034;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#034;^3.0.1&#034;<\/span><br \/>\n  <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<hr \/>\n<h3>3. WebSocket \u670d\u52a1\u5668<\/h3>\n<h4>3.1 \u57fa\u7840\u670d\u52a1\u5668<\/h4>\n<p><span class=\"token comment\">\/\/ server.js<\/span><br \/>\n<span class=\"token keyword\">const<\/span> WebSocket <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">require<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;ws&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token keyword\">const<\/span> http <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">require<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;http&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> SignalingServer <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">require<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;.\/src\/SignalingServer&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token keyword\">const<\/span> <span class=\"token constant\">PORT<\/span> <span class=\"token operator\">&#061;<\/span> process<span class=\"token punctuation\">.<\/span>env<span class=\"token punctuation\">.<\/span><span class=\"token constant\">PORT<\/span> <span class=\"token operator\">||<\/span> <span class=\"token number\">8080<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ \u521b\u5efa HTTP \u670d\u52a1\u5668<\/span><br \/>\n<span class=\"token keyword\">const<\/span> server <span class=\"token operator\">&#061;<\/span> http<span class=\"token punctuation\">.<\/span><span class=\"token function\">createServer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">req<span class=\"token punctuation\">,<\/span> res<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    res<span class=\"token punctuation\">.<\/span><span class=\"token function\">writeHead<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">200<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token string-property property\">&#039;Content-Type&#039;<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;text\/plain&#039;<\/span> <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    res<span class=\"token punctuation\">.<\/span><span class=\"token function\">end<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;WebRTC Signaling Server&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ \u521b\u5efa WebSocket \u670d\u52a1\u5668<\/span><br \/>\n<span class=\"token keyword\">const<\/span> wss <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">WebSocket<span class=\"token punctuation\">.<\/span>Server<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span> server <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ \u521b\u5efa\u4fe1\u4ee4\u670d\u52a1\u5668\u5b9e\u4f8b<\/span><br \/>\n<span class=\"token keyword\">const<\/span> signalingServer <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">SignalingServer<\/span><span class=\"token punctuation\">(<\/span>wss<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ \u542f\u52a8\u670d\u52a1\u5668<\/span><br \/>\nserver<span class=\"token punctuation\">.<\/span><span class=\"token function\">listen<\/span><span class=\"token punctuation\">(<\/span><span class=\"token constant\">PORT<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">Signaling server running on port <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span><span class=\"token constant\">PORT<\/span><span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<h4>3.2 SignalingServer \u7c7b<\/h4>\n<p><span class=\"token comment\">\/\/ src\/SignalingServer.js<\/span><br \/>\n<span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token literal-property property\">v4<\/span><span class=\"token operator\">:<\/span> uuidv4 <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">require<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;uuid&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> RoomManager <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">require<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;.\/RoomManager&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> MessageHandler <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">require<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;.\/MessageHandler&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">SignalingServer<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">constructor<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">wss<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>wss <span class=\"token operator\">&#061;<\/span> wss<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>clients <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">Map<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ clientId -&gt; { ws, userId, roomId }<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>roomManager <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">RoomManager<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>messageHandler <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">MessageHandler<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">this<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">init<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token function\">init<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>wss<span class=\"token punctuation\">.<\/span><span class=\"token function\">on<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;connection&#039;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token parameter\">ws<span class=\"token punctuation\">,<\/span> req<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleConnection<\/span><span class=\"token punctuation\">(<\/span>ws<span class=\"token punctuation\">,<\/span> req<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token function\">handleConnection<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">ws<span class=\"token punctuation\">,<\/span> req<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> clientId <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">uuidv4<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u4fdd\u5b58\u5ba2\u6237\u7aef\u4fe1\u606f<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>clients<span class=\"token punctuation\">.<\/span><span class=\"token function\">set<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            ws<span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">userId<\/span><span class=\"token operator\">:<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">roomId<\/span><span class=\"token operator\">:<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">connectedAt<\/span><span class=\"token operator\">:<\/span> Date<span class=\"token punctuation\">.<\/span><span class=\"token function\">now<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">Client connected: <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>clientId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u53d1\u9001\u6b22\u8fce\u6d88\u606f<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">send<\/span><span class=\"token punctuation\">(<\/span>ws<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;welcome&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            clientId<br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u5904\u7406\u6d88\u606f<\/span><br \/>\n        ws<span class=\"token punctuation\">.<\/span><span class=\"token function\">on<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;message&#039;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token parameter\">data<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">try<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token keyword\">const<\/span> message <span class=\"token operator\">&#061;<\/span> <span class=\"token constant\">JSON<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">parse<\/span><span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>messageHandler<span class=\"token punctuation\">.<\/span><span class=\"token function\">handle<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span>error<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                console<span class=\"token punctuation\">.<\/span><span class=\"token function\">error<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;Invalid message:&#039;<\/span><span class=\"token punctuation\">,<\/span> error<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">send<\/span><span class=\"token punctuation\">(<\/span>ws<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                    <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;error&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token literal-property property\">message<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;Invalid message format&#039;<\/span><br \/>\n                <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u5904\u7406\u65ad\u5f00\u8fde\u63a5<\/span><br \/>\n        ws<span class=\"token punctuation\">.<\/span><span class=\"token function\">on<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;close&#039;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleDisconnect<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u5904\u7406\u9519\u8bef<\/span><br \/>\n        ws<span class=\"token punctuation\">.<\/span><span class=\"token function\">on<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;error&#039;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token parameter\">error<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">error<\/span><span class=\"token punctuation\">(<\/span><span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">Client <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>clientId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token string\"> error:<\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">,<\/span> error<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u5fc3\u8df3\u68c0\u6d4b<\/span><br \/>\n        ws<span class=\"token punctuation\">.<\/span>isAlive <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        ws<span class=\"token punctuation\">.<\/span><span class=\"token function\">on<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;pong&#039;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            ws<span class=\"token punctuation\">.<\/span>isAlive <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token function\">handleDisconnect<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">clientId<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> client <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>clients<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>client<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u79bb\u5f00\u623f\u95f4<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>client<span class=\"token punctuation\">.<\/span>roomId<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>roomManager<span class=\"token punctuation\">.<\/span><span class=\"token function\">leaveRoom<\/span><span class=\"token punctuation\">(<\/span>client<span class=\"token punctuation\">.<\/span>roomId<span class=\"token punctuation\">,<\/span> clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>            <span class=\"token comment\">\/\/ \u901a\u77e5\u623f\u95f4\u5185\u5176\u4ed6\u4eba<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">broadcastToRoom<\/span><span class=\"token punctuation\">(<\/span>client<span class=\"token punctuation\">.<\/span>roomId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;user-left&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">userId<\/span><span class=\"token operator\">:<\/span> client<span class=\"token punctuation\">.<\/span>userId<span class=\"token punctuation\">,<\/span><br \/>\n                clientId<br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u5220\u9664\u5ba2\u6237\u7aef<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>clients<span class=\"token punctuation\">.<\/span><span class=\"token function\">delete<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">Client disconnected: <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>clientId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u53d1\u9001\u6d88\u606f\u7ed9\u5355\u4e2a\u5ba2\u6237\u7aef<\/span><br \/>\n    <span class=\"token function\">send<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">ws<span class=\"token punctuation\">,<\/span> message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>ws<span class=\"token punctuation\">.<\/span>readyState <span class=\"token operator\">&#061;&#061;&#061;<\/span> WebSocket<span class=\"token punctuation\">.<\/span><span class=\"token constant\">OPEN<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            ws<span class=\"token punctuation\">.<\/span><span class=\"token function\">send<\/span><span class=\"token punctuation\">(<\/span><span class=\"token constant\">JSON<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">stringify<\/span><span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u53d1\u9001\u6d88\u606f\u7ed9\u6307\u5b9a\u5ba2\u6237\u7aef<\/span><br \/>\n    <span class=\"token function\">sendTo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">clientId<span class=\"token punctuation\">,<\/span> message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> client <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>clients<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>client<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">send<\/span><span class=\"token punctuation\">(<\/span>client<span class=\"token punctuation\">.<\/span>ws<span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u5e7f\u64ad\u7ed9\u623f\u95f4\u5185\u6240\u6709\u4eba<\/span><br \/>\n    <span class=\"token function\">broadcastToRoom<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">roomId<span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">,<\/span> excludeClientId <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">null<\/span><\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> room <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>roomManager<span class=\"token punctuation\">.<\/span><span class=\"token function\">getRoom<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>room<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> memberId <span class=\"token keyword\">of<\/span> room<span class=\"token punctuation\">.<\/span>members<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>memberId <span class=\"token operator\">!&#061;&#061;<\/span> excludeClientId<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">sendTo<\/span><span class=\"token punctuation\">(<\/span>memberId<span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u542f\u52a8\u5fc3\u8df3\u68c0\u6d4b<\/span><br \/>\n    <span class=\"token function\">startHeartbeat<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token function\">setInterval<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>wss<span class=\"token punctuation\">.<\/span>clients<span class=\"token punctuation\">.<\/span><span class=\"token function\">forEach<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">ws<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>ws<span class=\"token punctuation\">.<\/span>isAlive <span class=\"token operator\">&#061;&#061;&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                    <span class=\"token keyword\">return<\/span> ws<span class=\"token punctuation\">.<\/span><span class=\"token function\">terminate<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token punctuation\">}<\/span><br \/>\n                ws<span class=\"token punctuation\">.<\/span>isAlive <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                ws<span class=\"token punctuation\">.<\/span><span class=\"token function\">ping<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">30000<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>module<span class=\"token punctuation\">.<\/span>exports <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span> SignalingServer <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<hr \/>\n<h3>4. \u623f\u95f4\u7ba1\u7406<\/h3>\n<h4>4.1 RoomManager \u7c7b<\/h4>\n<p><span class=\"token comment\">\/\/ src\/RoomManager.js<\/span><br \/>\n<span class=\"token keyword\">class<\/span> <span class=\"token class-name\">RoomManager<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">constructor<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>rooms <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">Map<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ roomId -&gt; Room<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u521b\u5efa\u623f\u95f4<\/span><br \/>\n    <span class=\"token function\">createRoom<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">roomId<span class=\"token punctuation\">,<\/span> options <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>rooms<span class=\"token punctuation\">.<\/span><span class=\"token function\">has<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>rooms<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token keyword\">const<\/span> room <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token literal-property property\">id<\/span><span class=\"token operator\">:<\/span> roomId<span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">members<\/span><span class=\"token operator\">:<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">Set<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">createdAt<\/span><span class=\"token operator\">:<\/span> Date<span class=\"token punctuation\">.<\/span><span class=\"token function\">now<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">maxMembers<\/span><span class=\"token operator\">:<\/span> options<span class=\"token punctuation\">.<\/span>maxMembers <span class=\"token operator\">||<\/span> <span class=\"token number\">10<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">isLocked<\/span><span class=\"token operator\">:<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">metadata<\/span><span class=\"token operator\">:<\/span> options<span class=\"token punctuation\">.<\/span>metadata <span class=\"token operator\">||<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>rooms<span class=\"token punctuation\">.<\/span><span class=\"token function\">set<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">,<\/span> room<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">Room created: <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>roomId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> room<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u52a0\u5165\u623f\u95f4<\/span><br \/>\n    <span class=\"token function\">joinRoom<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">roomId<span class=\"token punctuation\">,<\/span> clientId<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">let<\/span> room <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>rooms<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u623f\u95f4\u4e0d\u5b58\u5728\u5219\u521b\u5efa<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>room<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            room <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">createRoom<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u68c0\u67e5\u623f\u95f4\u662f\u5426\u5df2\u6ee1<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>room<span class=\"token punctuation\">.<\/span>members<span class=\"token punctuation\">.<\/span>size <span class=\"token operator\">&gt;&#061;<\/span> room<span class=\"token punctuation\">.<\/span>maxMembers<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token literal-property property\">success<\/span><span class=\"token operator\">:<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token literal-property property\">error<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;Room is full&#039;<\/span> <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u68c0\u67e5\u623f\u95f4\u662f\u5426\u9501\u5b9a<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>room<span class=\"token punctuation\">.<\/span>isLocked<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token literal-property property\">success<\/span><span class=\"token operator\">:<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token literal-property property\">error<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;Room is locked&#039;<\/span> <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        room<span class=\"token punctuation\">.<\/span>members<span class=\"token punctuation\">.<\/span><span class=\"token function\">add<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">Client <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>clientId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token string\"> joined room <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>roomId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token literal-property property\">success<\/span><span class=\"token operator\">:<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">room<\/span><span class=\"token operator\">:<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">getRoomInfo<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u79bb\u5f00\u623f\u95f4<\/span><br \/>\n    <span class=\"token function\">leaveRoom<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">roomId<span class=\"token punctuation\">,<\/span> clientId<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> room <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>rooms<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>room<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        room<span class=\"token punctuation\">.<\/span>members<span class=\"token punctuation\">.<\/span><span class=\"token function\">delete<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">Client <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>clientId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token string\"> left room <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>roomId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u623f\u95f4\u4e3a\u7a7a\u5219\u5220\u9664<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>room<span class=\"token punctuation\">.<\/span>members<span class=\"token punctuation\">.<\/span>size <span class=\"token operator\">&#061;&#061;&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>rooms<span class=\"token punctuation\">.<\/span><span class=\"token function\">delete<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">Room deleted: <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>roomId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u83b7\u53d6\u623f\u95f4<\/span><br \/>\n    <span class=\"token function\">getRoom<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">roomId<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>rooms<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u83b7\u53d6\u623f\u95f4\u4fe1\u606f (\u4e0d\u5305\u542b\u654f\u611f\u6570\u636e)<\/span><br \/>\n    <span class=\"token function\">getRoomInfo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">roomId<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> room <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>rooms<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>room<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token literal-property property\">id<\/span><span class=\"token operator\">:<\/span> room<span class=\"token punctuation\">.<\/span>id<span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">memberCount<\/span><span class=\"token operator\">:<\/span> room<span class=\"token punctuation\">.<\/span>members<span class=\"token punctuation\">.<\/span>size<span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">members<\/span><span class=\"token operator\">:<\/span> Array<span class=\"token punctuation\">.<\/span><span class=\"token function\">from<\/span><span class=\"token punctuation\">(<\/span>room<span class=\"token punctuation\">.<\/span>members<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">maxMembers<\/span><span class=\"token operator\">:<\/span> room<span class=\"token punctuation\">.<\/span>maxMembers<span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">isLocked<\/span><span class=\"token operator\">:<\/span> room<span class=\"token punctuation\">.<\/span>isLocked<br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u83b7\u53d6\u6240\u6709\u623f\u95f4\u5217\u8868<\/span><br \/>\n    <span class=\"token function\">getRoomList<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> list <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">[<\/span>roomId<span class=\"token punctuation\">,<\/span> room<span class=\"token punctuation\">]<\/span> <span class=\"token keyword\">of<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>rooms<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            list<span class=\"token punctuation\">.<\/span><span class=\"token function\">push<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token literal-property property\">id<\/span><span class=\"token operator\">:<\/span> roomId<span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">memberCount<\/span><span class=\"token operator\">:<\/span> room<span class=\"token punctuation\">.<\/span>members<span class=\"token punctuation\">.<\/span>size<span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">maxMembers<\/span><span class=\"token operator\">:<\/span> room<span class=\"token punctuation\">.<\/span>maxMembers<br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> list<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u9501\u5b9a\/\u89e3\u9501\u623f\u95f4<\/span><br \/>\n    <span class=\"token function\">setRoomLock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">roomId<span class=\"token punctuation\">,<\/span> isLocked<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> room <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>rooms<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>room<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            room<span class=\"token punctuation\">.<\/span>isLocked <span class=\"token operator\">&#061;<\/span> isLocked<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>module<span class=\"token punctuation\">.<\/span>exports <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span> RoomManager <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<hr \/>\n<h3>5. \u4fe1\u4ee4\u6d88\u606f\u5904\u7406<\/h3>\n<h4>5.1 MessageHandler \u7c7b<\/h4>\n<p><span class=\"token comment\">\/\/ src\/MessageHandler.js<\/span><br \/>\n<span class=\"token keyword\">class<\/span> <span class=\"token class-name\">MessageHandler<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">constructor<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">server<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server <span class=\"token operator\">&#061;<\/span> server<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token function\">handle<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">clientId<span class=\"token punctuation\">,<\/span> message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> type <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> message<span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">switch<\/span> <span class=\"token punctuation\">(<\/span>type<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;register&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleRegister<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;join&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleJoin<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;leave&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleLeave<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;offer&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleOffer<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;answer&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleAnswer<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;candidate&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleCandidate<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;message&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleMessage<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">default<\/span><span class=\"token operator\">:<\/span><br \/>\n                console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">Unknown message type: <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>type<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u7528\u6237\u6ce8\u518c<\/span><br \/>\n    <span class=\"token function\">handleRegister<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">clientId<span class=\"token punctuation\">,<\/span> message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> userId <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> message<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> client <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span>clients<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>client<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            client<span class=\"token punctuation\">.<\/span>userId <span class=\"token operator\">&#061;<\/span> userId <span class=\"token operator\">||<\/span> clientId<span class=\"token punctuation\">;<\/span><\/p>\n<p>            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span><span class=\"token function\">sendTo<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;registered&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">userId<\/span><span class=\"token operator\">:<\/span> client<span class=\"token punctuation\">.<\/span>userId<br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u52a0\u5165\u623f\u95f4<\/span><br \/>\n    <span class=\"token function\">handleJoin<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">clientId<span class=\"token punctuation\">,<\/span> message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> roomId <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> message<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> client <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span>clients<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>client<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u5982\u679c\u5df2\u5728\u5176\u4ed6\u623f\u95f4,\u5148\u79bb\u5f00<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>client<span class=\"token punctuation\">.<\/span>roomId<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleLeave<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token literal-property property\">roomId<\/span><span class=\"token operator\">:<\/span> client<span class=\"token punctuation\">.<\/span>roomId <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u52a0\u5165\u65b0\u623f\u95f4<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> result <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span>roomManager<span class=\"token punctuation\">.<\/span><span class=\"token function\">joinRoom<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">,<\/span> clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>result<span class=\"token punctuation\">.<\/span>success<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            client<span class=\"token punctuation\">.<\/span>roomId <span class=\"token operator\">&#061;<\/span> roomId<span class=\"token punctuation\">;<\/span><\/p>\n<p>            <span class=\"token comment\">\/\/ \u901a\u77e5\u52a0\u5165\u8005<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span><span class=\"token function\">sendTo<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;joined&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                roomId<span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">members<\/span><span class=\"token operator\">:<\/span> result<span class=\"token punctuation\">.<\/span>room<span class=\"token punctuation\">.<\/span>members<span class=\"token punctuation\">.<\/span><span class=\"token function\">filter<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">id<\/span> <span class=\"token operator\">&#061;&gt;<\/span> id <span class=\"token operator\">!&#061;&#061;<\/span> clientId<span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>            <span class=\"token comment\">\/\/ \u901a\u77e5\u623f\u95f4\u5185\u5176\u4ed6\u4eba<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span><span class=\"token function\">broadcastToRoom<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;user-joined&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">userId<\/span><span class=\"token operator\">:<\/span> client<span class=\"token punctuation\">.<\/span>userId<span class=\"token punctuation\">,<\/span><br \/>\n                clientId<br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span><span class=\"token function\">sendTo<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;join-error&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">error<\/span><span class=\"token operator\">:<\/span> result<span class=\"token punctuation\">.<\/span>error<br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u79bb\u5f00\u623f\u95f4<\/span><br \/>\n    <span class=\"token function\">handleLeave<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">clientId<span class=\"token punctuation\">,<\/span> message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> roomId <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> message<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> client <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span>clients<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>client <span class=\"token operator\">||<\/span> client<span class=\"token punctuation\">.<\/span>roomId <span class=\"token operator\">!&#061;&#061;<\/span> roomId<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span>roomManager<span class=\"token punctuation\">.<\/span><span class=\"token function\">leaveRoom<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">,<\/span> clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u901a\u77e5\u623f\u95f4\u5185\u5176\u4ed6\u4eba<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span><span class=\"token function\">broadcastToRoom<\/span><span class=\"token punctuation\">(<\/span>roomId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;user-left&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">userId<\/span><span class=\"token operator\">:<\/span> client<span class=\"token punctuation\">.<\/span>userId<span class=\"token punctuation\">,<\/span><br \/>\n            clientId<br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        client<span class=\"token punctuation\">.<\/span>roomId <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span><span class=\"token function\">sendTo<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;left&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            roomId<br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u5904\u7406 Offer<\/span><br \/>\n    <span class=\"token function\">handleOffer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">clientId<span class=\"token punctuation\">,<\/span> message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> targetId<span class=\"token punctuation\">,<\/span> sdp <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> message<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> client <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span>clients<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>client<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span><span class=\"token function\">sendTo<\/span><span class=\"token punctuation\">(<\/span>targetId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;offer&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">fromId<\/span><span class=\"token operator\">:<\/span> clientId<span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">fromUserId<\/span><span class=\"token operator\">:<\/span> client<span class=\"token punctuation\">.<\/span>userId<span class=\"token punctuation\">,<\/span><br \/>\n            sdp<br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u5904\u7406 Answer<\/span><br \/>\n    <span class=\"token function\">handleAnswer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">clientId<span class=\"token punctuation\">,<\/span> message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> targetId<span class=\"token punctuation\">,<\/span> sdp <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> message<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> client <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span>clients<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>client<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span><span class=\"token function\">sendTo<\/span><span class=\"token punctuation\">(<\/span>targetId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;answer&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">fromId<\/span><span class=\"token operator\">:<\/span> clientId<span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">fromUserId<\/span><span class=\"token operator\">:<\/span> client<span class=\"token punctuation\">.<\/span>userId<span class=\"token punctuation\">,<\/span><br \/>\n            sdp<br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u5904\u7406 ICE Candidate<\/span><br \/>\n    <span class=\"token function\">handleCandidate<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">clientId<span class=\"token punctuation\">,<\/span> message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> targetId<span class=\"token punctuation\">,<\/span> candidate <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> message<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> client <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span>clients<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>client<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span><span class=\"token function\">sendTo<\/span><span class=\"token punctuation\">(<\/span>targetId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;candidate&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">fromId<\/span><span class=\"token operator\">:<\/span> clientId<span class=\"token punctuation\">,<\/span><br \/>\n            candidate<br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u5904\u7406\u81ea\u5b9a\u4e49\u6d88\u606f<\/span><br \/>\n    <span class=\"token function\">handleMessage<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">clientId<span class=\"token punctuation\">,<\/span> message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> targetId<span class=\"token punctuation\">,<\/span> content <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> message<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> client <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span>clients<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>client<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>targetId<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token comment\">\/\/ \u53d1\u9001\u7ed9\u6307\u5b9a\u7528\u6237<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span><span class=\"token function\">sendTo<\/span><span class=\"token punctuation\">(<\/span>targetId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;message&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">fromId<\/span><span class=\"token operator\">:<\/span> clientId<span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">fromUserId<\/span><span class=\"token operator\">:<\/span> client<span class=\"token punctuation\">.<\/span>userId<span class=\"token punctuation\">,<\/span><br \/>\n                content<br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>client<span class=\"token punctuation\">.<\/span>roomId<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token comment\">\/\/ \u5e7f\u64ad\u7ed9\u623f\u95f4<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>server<span class=\"token punctuation\">.<\/span><span class=\"token function\">broadcastToRoom<\/span><span class=\"token punctuation\">(<\/span>client<span class=\"token punctuation\">.<\/span>roomId<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;message&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">fromId<\/span><span class=\"token operator\">:<\/span> clientId<span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">fromUserId<\/span><span class=\"token operator\">:<\/span> client<span class=\"token punctuation\">.<\/span>userId<span class=\"token punctuation\">,<\/span><br \/>\n                content<br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>module<span class=\"token punctuation\">.<\/span>exports <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span> MessageHandler <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<hr \/>\n<h3>6. \u5ba2\u6237\u7aef\u5b9e\u73b0<\/h3>\n<h4>6.1 HTML \u9875\u9762<\/h4>\n<p><span class=\"token comment\">&lt;!&#8211; client\/index.html &#8211;&gt;<\/span><br \/>\n<span class=\"token doctype\"><span class=\"token punctuation\">&lt;!<\/span><span class=\"token doctype-tag\">DOCTYPE<\/span> <span class=\"token name\">html<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>html<\/span> <span class=\"token attr-name\">lang<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>zh-CN<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>head<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>meta<\/span> <span class=\"token attr-name\">charset<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>UTF-8<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>meta<\/span> <span class=\"token attr-name\">name<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>viewport<span class=\"token punctuation\">&#034;<\/span><\/span> <span class=\"token attr-name\">content<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>width&#061;device-width, initial-scale&#061;1.0<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>title<\/span><span class=\"token punctuation\">&gt;<\/span><\/span>WebRTC Video Chat<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>title<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>link<\/span> <span class=\"token attr-name\">rel<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>stylesheet<span class=\"token punctuation\">&#034;<\/span><\/span> <span class=\"token attr-name\">href<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>style.css<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>head<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>body<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>div<\/span> <span class=\"token attr-name\">class<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>container<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n        <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>h1<\/span><span class=\"token punctuation\">&gt;<\/span><\/span>WebRTC Video Chat<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>h1<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><\/p>\n<p>        <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>div<\/span> <span class=\"token attr-name\">class<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>controls<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n            <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>input<\/span> <span class=\"token attr-name\">type<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>text<span class=\"token punctuation\">&#034;<\/span><\/span> <span class=\"token attr-name\">id<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>roomId<span class=\"token punctuation\">&#034;<\/span><\/span> <span class=\"token attr-name\">placeholder<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>\u623f\u95f4 ID<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n            <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>button<\/span> <span class=\"token attr-name\">id<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>joinBtn<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span>\u52a0\u5165\u623f\u95f4<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>button<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n            <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>button<\/span> <span class=\"token attr-name\">id<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>leaveBtn<span class=\"token punctuation\">&#034;<\/span><\/span> <span class=\"token attr-name\">disabled<\/span><span class=\"token punctuation\">&gt;<\/span><\/span>\u79bb\u5f00\u623f\u95f4<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>button<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n        <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>div<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><\/p>\n<p>        <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>div<\/span> <span class=\"token attr-name\">class<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>video-container<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n            <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>div<\/span> <span class=\"token attr-name\">class<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>video-wrapper<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n                <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>video<\/span> <span class=\"token attr-name\">id<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>localVideo<span class=\"token punctuation\">&#034;<\/span><\/span> <span class=\"token attr-name\">autoplay<\/span> <span class=\"token attr-name\">muted<\/span> <span class=\"token attr-name\">playsinline<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>video<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n                <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>span<\/span> <span class=\"token attr-name\">class<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>label<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span>\u672c\u5730\u89c6\u9891<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>span<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n            <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>div<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n            <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>div<\/span> <span class=\"token attr-name\">id<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>remoteVideos<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>div<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n        <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>div<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><\/p>\n<p>        <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>div<\/span> <span class=\"token attr-name\">class<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>status<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n            <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>span<\/span> <span class=\"token attr-name\">id<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>connectionStatus<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span>\u672a\u8fde\u63a5<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>span<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n        <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>div<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>div<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><\/p>\n<p>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>script<\/span> <span class=\"token attr-name\">src<\/span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">&#061;<\/span><span class=\"token punctuation\">&#034;<\/span>app.js<span class=\"token punctuation\">&#034;<\/span><\/span><span class=\"token punctuation\">&gt;<\/span><\/span><span class=\"token script\"><\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>script<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>body<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><br \/>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>html<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><\/p>\n<h4>6.2 \u5ba2\u6237\u7aef JavaScript<\/h4>\n<p><span class=\"token comment\">\/\/ client\/app.js<\/span><br \/>\n<span class=\"token keyword\">class<\/span> <span class=\"token class-name\">WebRTCClient<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">constructor<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>ws <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>clientId <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>roomId <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>localStream <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>peerConnections <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">Map<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ peerId -&gt; RTCPeerConnection<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>config <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token literal-property property\">iceServers<\/span><span class=\"token operator\">:<\/span> <span class=\"token punctuation\">[<\/span><br \/>\n                <span class=\"token punctuation\">{<\/span> <span class=\"token literal-property property\">urls<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;stun:stun.l.google.com:19302&#039;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n            <span class=\"token punctuation\">]<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">init<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token function\">init<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token comment\">\/\/ \u7ed1\u5b9a UI \u4e8b\u4ef6<\/span><br \/>\n        document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;joinBtn&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">onclick<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">joinRoom<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;leaveBtn&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">onclick<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">leaveRoom<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u8fde\u63a5\u4fe1\u4ee4\u670d\u52a1\u5668<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">connectSignaling<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u8fde\u63a5\u4fe1\u4ee4\u670d\u52a1\u5668<\/span><br \/>\n    <span class=\"token function\">connectSignaling<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> wsUrl <span class=\"token operator\">&#061;<\/span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">ws:\/\/<\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>window<span class=\"token punctuation\">.<\/span>location<span class=\"token punctuation\">.<\/span>hostname<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token string\">:8080<\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>ws <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">WebSocket<\/span><span class=\"token punctuation\">(<\/span>wsUrl<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>ws<span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">onopen<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;Connected to signaling server&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">updateStatus<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;\u5df2\u8fde\u63a5&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>ws<span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">onclose<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;Disconnected from signaling server&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">updateStatus<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;\u5df2\u65ad\u5f00&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token comment\">\/\/ \u5c1d\u8bd5\u91cd\u8fde<\/span><br \/>\n            <span class=\"token function\">setTimeout<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">connectSignaling<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">3000<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>ws<span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">onerror<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token parameter\">error<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">error<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;WebSocket error:&#039;<\/span><span class=\"token punctuation\">,<\/span> error<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>ws<span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">onmessage<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token parameter\">event<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">const<\/span> message <span class=\"token operator\">&#061;<\/span> <span class=\"token constant\">JSON<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">parse<\/span><span class=\"token punctuation\">(<\/span>event<span class=\"token punctuation\">.<\/span>data<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleMessage<\/span><span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u5904\u7406\u4fe1\u4ee4\u6d88\u606f<\/span><br \/>\n    <span class=\"token function\">handleMessage<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;Received:&#039;<\/span><span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">.<\/span>type<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">switch<\/span> <span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">.<\/span>type<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;welcome&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>clientId <span class=\"token operator\">&#061;<\/span> message<span class=\"token punctuation\">.<\/span>clientId<span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;joined&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleJoined<\/span><span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;user-joined&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleUserJoined<\/span><span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;user-left&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleUserLeft<\/span><span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;offer&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleOffer<\/span><span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;answer&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleAnswer<\/span><span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">case<\/span> <span class=\"token string\">&#039;candidate&#039;<\/span><span class=\"token operator\">:<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">handleCandidate<\/span><span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u53d1\u9001\u4fe1\u4ee4\u6d88\u606f<\/span><br \/>\n    <span class=\"token function\">send<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>ws<span class=\"token punctuation\">.<\/span>readyState <span class=\"token operator\">&#061;&#061;&#061;<\/span> WebSocket<span class=\"token punctuation\">.<\/span><span class=\"token constant\">OPEN<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>ws<span class=\"token punctuation\">.<\/span><span class=\"token function\">send<\/span><span class=\"token punctuation\">(<\/span><span class=\"token constant\">JSON<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">stringify<\/span><span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u52a0\u5165\u623f\u95f4<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token function\">joinRoom<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> roomId <span class=\"token operator\">&#061;<\/span> document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;roomId&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>value<span class=\"token punctuation\">.<\/span><span class=\"token function\">trim<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>roomId<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token function\">alert<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;\u8bf7\u8f93\u5165\u623f\u95f4 ID&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u83b7\u53d6\u672c\u5730\u5a92\u4f53\u6d41<\/span><br \/>\n        <span class=\"token keyword\">try<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>localStream <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> navigator<span class=\"token punctuation\">.<\/span>mediaDevices<span class=\"token punctuation\">.<\/span><span class=\"token function\">getUserMedia<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token literal-property property\">video<\/span><span class=\"token operator\">:<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">audio<\/span><span class=\"token operator\">:<\/span> <span class=\"token boolean\">true<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>            document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;localVideo&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>srcObject <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>localStream<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span>error<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">error<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;Failed to get media:&#039;<\/span><span class=\"token punctuation\">,<\/span> error<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token function\">alert<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;\u65e0\u6cd5\u83b7\u53d6\u6444\u50cf\u5934\/\u9ea6\u514b\u98ce&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u53d1\u9001\u52a0\u5165\u8bf7\u6c42<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">send<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;join&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            roomId<br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>roomId <span class=\"token operator\">&#061;<\/span> roomId<span class=\"token punctuation\">;<\/span><br \/>\n        document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;joinBtn&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>disabled <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;leaveBtn&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>disabled <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u79bb\u5f00\u623f\u95f4<\/span><br \/>\n    <span class=\"token function\">leaveRoom<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">send<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;leave&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token literal-property property\">roomId<\/span><span class=\"token operator\">:<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>roomId<br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u5173\u95ed\u6240\u6709\u8fde\u63a5<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">[<\/span>peerId<span class=\"token punctuation\">,<\/span> pc<span class=\"token punctuation\">]<\/span> <span class=\"token keyword\">of<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>peerConnections<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            pc<span class=\"token punctuation\">.<\/span><span class=\"token function\">close<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>peerConnections<span class=\"token punctuation\">.<\/span><span class=\"token function\">clear<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u505c\u6b62\u672c\u5730\u6d41<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>localStream<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>localStream<span class=\"token punctuation\">.<\/span><span class=\"token function\">getTracks<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">forEach<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">track<\/span> <span class=\"token operator\">&#061;&gt;<\/span> track<span class=\"token punctuation\">.<\/span><span class=\"token function\">stop<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>localStream <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u6e05\u7406\u8fdc\u7a0b\u89c6\u9891<\/span><br \/>\n        document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;remoteVideos&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>innerHTML <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#039;&#039;<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;localVideo&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>srcObject <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>roomId <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;joinBtn&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>disabled <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;leaveBtn&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>disabled <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u5904\u7406\u52a0\u5165\u6210\u529f<\/span><br \/>\n    <span class=\"token function\">handleJoined<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;Joined room, members:&#039;<\/span><span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">.<\/span>members<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u5411\u623f\u95f4\u5185\u5df2\u6709\u6210\u5458\u53d1\u8d77\u8fde\u63a5<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> memberId <span class=\"token keyword\">of<\/span> message<span class=\"token punctuation\">.<\/span>members<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">createPeerConnection<\/span><span class=\"token punctuation\">(<\/span>memberId<span class=\"token punctuation\">,<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u5904\u7406\u65b0\u7528\u6237\u52a0\u5165<\/span><br \/>\n    <span class=\"token function\">handleUserJoined<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;User joined:&#039;<\/span><span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">.<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token comment\">\/\/ \u7b49\u5f85\u65b0\u7528\u6237\u53d1\u8d77 Offer<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u5904\u7406\u7528\u6237\u79bb\u5f00<\/span><br \/>\n    <span class=\"token function\">handleUserLeft<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;User left:&#039;<\/span><span class=\"token punctuation\">,<\/span> message<span class=\"token punctuation\">.<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">const<\/span> pc <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>peerConnections<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">.<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>pc<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            pc<span class=\"token punctuation\">.<\/span><span class=\"token function\">close<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>peerConnections<span class=\"token punctuation\">.<\/span><span class=\"token function\">delete<\/span><span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">.<\/span>clientId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u79fb\u9664\u8fdc\u7a0b\u89c6\u9891<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> videoEl <span class=\"token operator\">&#061;<\/span> document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">video-<\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>message<span class=\"token punctuation\">.<\/span>clientId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>videoEl<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            videoEl<span class=\"token punctuation\">.<\/span>parentElement<span class=\"token punctuation\">.<\/span><span class=\"token function\">remove<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u521b\u5efa PeerConnection<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token function\">createPeerConnection<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">peerId<span class=\"token punctuation\">,<\/span> isInitiator<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> pc <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">RTCPeerConnection<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>config<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>peerConnections<span class=\"token punctuation\">.<\/span><span class=\"token function\">set<\/span><span class=\"token punctuation\">(<\/span>peerId<span class=\"token punctuation\">,<\/span> pc<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u6dfb\u52a0\u672c\u5730\u6d41<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>localStream<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>localStream<span class=\"token punctuation\">.<\/span><span class=\"token function\">getTracks<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">forEach<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">track<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                pc<span class=\"token punctuation\">.<\/span><span class=\"token function\">addTrack<\/span><span class=\"token punctuation\">(<\/span>track<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>localStream<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u5904\u7406 ICE Candidate<\/span><br \/>\n        pc<span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">onicecandidate<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token parameter\">event<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>event<span class=\"token punctuation\">.<\/span>candidate<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">send<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n                    <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;candidate&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token literal-property property\">targetId<\/span><span class=\"token operator\">:<\/span> peerId<span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token literal-property property\">candidate<\/span><span class=\"token operator\">:<\/span> event<span class=\"token punctuation\">.<\/span>candidate<br \/>\n                <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u5904\u7406\u8fdc\u7a0b\u6d41<\/span><br \/>\n        pc<span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">ontrack<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token parameter\">event<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">addRemoteVideo<\/span><span class=\"token punctuation\">(<\/span>peerId<span class=\"token punctuation\">,<\/span> event<span class=\"token punctuation\">.<\/span>streams<span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u5904\u7406\u8fde\u63a5\u72b6\u6001\u53d8\u5316<\/span><br \/>\n        pc<span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">onconnectionstatechange<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&gt;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">Connection state with <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>peerId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token string\">:<\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">,<\/span> pc<span class=\"token punctuation\">.<\/span>connectionState<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ \u5982\u679c\u662f\u53d1\u8d77\u65b9,\u521b\u5efa Offer<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>isInitiator<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">try<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token keyword\">const<\/span> offer <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> pc<span class=\"token punctuation\">.<\/span><span class=\"token function\">createOffer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">await<\/span> pc<span class=\"token punctuation\">.<\/span><span class=\"token function\">setLocalDescription<\/span><span class=\"token punctuation\">(<\/span>offer<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>                <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">send<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n                    <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;offer&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token literal-property property\">targetId<\/span><span class=\"token operator\">:<\/span> peerId<span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token literal-property property\">sdp<\/span><span class=\"token operator\">:<\/span> offer<br \/>\n                <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span>error<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                console<span class=\"token punctuation\">.<\/span><span class=\"token function\">error<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;Failed to create offer:&#039;<\/span><span class=\"token punctuation\">,<\/span> error<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token keyword\">return<\/span> pc<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u5904\u7406 Offer<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token function\">handleOffer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> fromId<span class=\"token punctuation\">,<\/span> sdp <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> message<span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">let<\/span> pc <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>peerConnections<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>fromId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>pc<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            pc <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">createPeerConnection<\/span><span class=\"token punctuation\">(<\/span>fromId<span class=\"token punctuation\">,<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token keyword\">try<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">await<\/span> pc<span class=\"token punctuation\">.<\/span><span class=\"token function\">setRemoteDescription<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">new<\/span> <span class=\"token class-name\">RTCSessionDescription<\/span><span class=\"token punctuation\">(<\/span>sdp<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">const<\/span> answer <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> pc<span class=\"token punctuation\">.<\/span><span class=\"token function\">createAnswer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">await<\/span> pc<span class=\"token punctuation\">.<\/span><span class=\"token function\">setLocalDescription<\/span><span class=\"token punctuation\">(<\/span>answer<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>            <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">send<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token literal-property property\">type<\/span><span class=\"token operator\">:<\/span> <span class=\"token string\">&#039;answer&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">targetId<\/span><span class=\"token operator\">:<\/span> fromId<span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token literal-property property\">sdp<\/span><span class=\"token operator\">:<\/span> answer<br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span>error<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">error<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;Failed to handle offer:&#039;<\/span><span class=\"token punctuation\">,<\/span> error<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u5904\u7406 Answer<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token function\">handleAnswer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> fromId<span class=\"token punctuation\">,<\/span> sdp <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> message<span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">const<\/span> pc <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>peerConnections<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>fromId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>pc<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">try<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token keyword\">await<\/span> pc<span class=\"token punctuation\">.<\/span><span class=\"token function\">setRemoteDescription<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">new<\/span> <span class=\"token class-name\">RTCSessionDescription<\/span><span class=\"token punctuation\">(<\/span>sdp<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span>error<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                console<span class=\"token punctuation\">.<\/span><span class=\"token function\">error<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;Failed to handle answer:&#039;<\/span><span class=\"token punctuation\">,<\/span> error<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u5904\u7406 ICE Candidate<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token function\">handleCandidate<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">message<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span> fromId<span class=\"token punctuation\">,<\/span> candidate <span class=\"token punctuation\">}<\/span> <span class=\"token operator\">&#061;<\/span> message<span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">const<\/span> pc <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>peerConnections<span class=\"token punctuation\">.<\/span><span class=\"token function\">get<\/span><span class=\"token punctuation\">(<\/span>fromId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>pc<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">try<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token keyword\">await<\/span> pc<span class=\"token punctuation\">.<\/span><span class=\"token function\">addIceCandidate<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">new<\/span> <span class=\"token class-name\">RTCIceCandidate<\/span><span class=\"token punctuation\">(<\/span>candidate<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span>error<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                console<span class=\"token punctuation\">.<\/span><span class=\"token function\">error<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;Failed to add ICE candidate:&#039;<\/span><span class=\"token punctuation\">,<\/span> error<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u6dfb\u52a0\u8fdc\u7a0b\u89c6\u9891<\/span><br \/>\n    <span class=\"token function\">addRemoteVideo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">peerId<span class=\"token punctuation\">,<\/span> stream<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">let<\/span> videoEl <span class=\"token operator\">&#061;<\/span> document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">video-<\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>peerId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>videoEl<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">const<\/span> wrapper <span class=\"token operator\">&#061;<\/span> document<span class=\"token punctuation\">.<\/span><span class=\"token function\">createElement<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;div&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            wrapper<span class=\"token punctuation\">.<\/span>className <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#039;video-wrapper&#039;<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>            videoEl <span class=\"token operator\">&#061;<\/span> document<span class=\"token punctuation\">.<\/span><span class=\"token function\">createElement<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;video&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            videoEl<span class=\"token punctuation\">.<\/span>id <span class=\"token operator\">&#061;<\/span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">video-<\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>peerId<span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">;<\/span><br \/>\n            videoEl<span class=\"token punctuation\">.<\/span>autoplay <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            videoEl<span class=\"token punctuation\">.<\/span>playsinline <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>            <span class=\"token keyword\">const<\/span> label <span class=\"token operator\">&#061;<\/span> document<span class=\"token punctuation\">.<\/span><span class=\"token function\">createElement<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;span&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            label<span class=\"token punctuation\">.<\/span>className <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#039;label&#039;<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            label<span class=\"token punctuation\">.<\/span>textContent <span class=\"token operator\">&#061;<\/span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">&#096;<\/span><span class=\"token string\">\u8fdc\u7a0b: <\/span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${<\/span>peerId<span class=\"token punctuation\">.<\/span><span class=\"token function\">slice<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">8<\/span><span class=\"token punctuation\">)<\/span><span class=\"token interpolation-punctuation punctuation\">}<\/span><\/span><span class=\"token template-punctuation string\">&#096;<\/span><\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>            wrapper<span class=\"token punctuation\">.<\/span><span class=\"token function\">appendChild<\/span><span class=\"token punctuation\">(<\/span>videoEl<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            wrapper<span class=\"token punctuation\">.<\/span><span class=\"token function\">appendChild<\/span><span class=\"token punctuation\">(<\/span>label<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;remoteVideos&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">appendChild<\/span><span class=\"token punctuation\">(<\/span>wrapper<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        videoEl<span class=\"token punctuation\">.<\/span>srcObject <span class=\"token operator\">&#061;<\/span> stream<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ \u66f4\u65b0\u72b6\u6001\u663e\u793a<\/span><br \/>\n    <span class=\"token function\">updateStatus<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">status<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        document<span class=\"token punctuation\">.<\/span><span class=\"token function\">getElementById<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;connectionStatus&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>textContent <span class=\"token operator\">&#061;<\/span> status<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ \u542f\u52a8\u5ba2\u6237\u7aef<\/span><br \/>\n<span class=\"token keyword\">const<\/span> client <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">WebRTCClient<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<h4>6.3 CSS \u6837\u5f0f<\/h4>\n<p><span class=\"token comment\">\/* client\/style.css *\/<\/span><br \/>\n<span class=\"token selector\">*<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">box-sizing<\/span><span class=\"token punctuation\">:<\/span> border-box<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">margin<\/span><span class=\"token punctuation\">:<\/span> 0<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">padding<\/span><span class=\"token punctuation\">:<\/span> 0<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">body<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">font-family<\/span><span class=\"token punctuation\">:<\/span> -apple-system<span class=\"token punctuation\">,<\/span> BlinkMacSystemFont<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#039;Segoe UI&#039;<\/span><span class=\"token punctuation\">,<\/span> Roboto<span class=\"token punctuation\">,<\/span> sans-serif<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">background<\/span><span class=\"token punctuation\">:<\/span> #1a1a2e<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">color<\/span><span class=\"token punctuation\">:<\/span> #eee<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">min-height<\/span><span class=\"token punctuation\">:<\/span> 100vh<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">.container<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">max-width<\/span><span class=\"token punctuation\">:<\/span> 1200px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">margin<\/span><span class=\"token punctuation\">:<\/span> 0 auto<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">padding<\/span><span class=\"token punctuation\">:<\/span> 20px<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">h1<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">text-align<\/span><span class=\"token punctuation\">:<\/span> center<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">margin-bottom<\/span><span class=\"token punctuation\">:<\/span> 20px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">color<\/span><span class=\"token punctuation\">:<\/span> #00d9ff<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">.controls<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">display<\/span><span class=\"token punctuation\">:<\/span> flex<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">gap<\/span><span class=\"token punctuation\">:<\/span> 10px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">justify-content<\/span><span class=\"token punctuation\">:<\/span> center<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">margin-bottom<\/span><span class=\"token punctuation\">:<\/span> 20px<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">input<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">padding<\/span><span class=\"token punctuation\">:<\/span> 10px 15px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">border<\/span><span class=\"token punctuation\">:<\/span> none<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">border-radius<\/span><span class=\"token punctuation\">:<\/span> 5px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">background<\/span><span class=\"token punctuation\">:<\/span> #16213e<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">color<\/span><span class=\"token punctuation\">:<\/span> #eee<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">font-size<\/span><span class=\"token punctuation\">:<\/span> 16px<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">button<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">padding<\/span><span class=\"token punctuation\">:<\/span> 10px 20px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">border<\/span><span class=\"token punctuation\">:<\/span> none<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">border-radius<\/span><span class=\"token punctuation\">:<\/span> 5px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">background<\/span><span class=\"token punctuation\">:<\/span> #00d9ff<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">color<\/span><span class=\"token punctuation\">:<\/span> #1a1a2e<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">font-size<\/span><span class=\"token punctuation\">:<\/span> 16px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">cursor<\/span><span class=\"token punctuation\">:<\/span> pointer<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">transition<\/span><span class=\"token punctuation\">:<\/span> background 0.3s<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">button:hover:not(:disabled)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">background<\/span><span class=\"token punctuation\">:<\/span> #00b8d9<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">button:disabled<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">background<\/span><span class=\"token punctuation\">:<\/span> #555<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">cursor<\/span><span class=\"token punctuation\">:<\/span> not-allowed<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">.video-container<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">display<\/span><span class=\"token punctuation\">:<\/span> flex<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">flex-wrap<\/span><span class=\"token punctuation\">:<\/span> wrap<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">gap<\/span><span class=\"token punctuation\">:<\/span> 20px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">justify-content<\/span><span class=\"token punctuation\">:<\/span> center<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">.video-wrapper<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">position<\/span><span class=\"token punctuation\">:<\/span> relative<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">background<\/span><span class=\"token punctuation\">:<\/span> #16213e<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">border-radius<\/span><span class=\"token punctuation\">:<\/span> 10px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">overflow<\/span><span class=\"token punctuation\">:<\/span> hidden<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">video<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">width<\/span><span class=\"token punctuation\">:<\/span> 400px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">height<\/span><span class=\"token punctuation\">:<\/span> 300px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">object-fit<\/span><span class=\"token punctuation\">:<\/span> cover<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">.label<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">position<\/span><span class=\"token punctuation\">:<\/span> absolute<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">bottom<\/span><span class=\"token punctuation\">:<\/span> 10px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">left<\/span><span class=\"token punctuation\">:<\/span> 10px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">background<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token function\">rgba<\/span><span class=\"token punctuation\">(<\/span>0<span class=\"token punctuation\">,<\/span> 0<span class=\"token punctuation\">,<\/span> 0<span class=\"token punctuation\">,<\/span> 0.7<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">padding<\/span><span class=\"token punctuation\">:<\/span> 5px 10px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">border-radius<\/span><span class=\"token punctuation\">:<\/span> 5px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">font-size<\/span><span class=\"token punctuation\">:<\/span> 14px<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">.status<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">text-align<\/span><span class=\"token punctuation\">:<\/span> center<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">margin-top<\/span><span class=\"token punctuation\">:<\/span> 20px<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">color<\/span><span class=\"token punctuation\">:<\/span> #888<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token selector\">#remoteVideos<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token property\">display<\/span><span class=\"token punctuation\">:<\/span> flex<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">flex-wrap<\/span><span class=\"token punctuation\">:<\/span> wrap<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token property\">gap<\/span><span class=\"token punctuation\">:<\/span> 20px<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<hr \/>\n<h3>7. \u5b8c\u6574\u4ee3\u7801<\/h3>\n<h4>7.1 \u5de5\u5177\u51fd\u6570<\/h4>\n<p><span class=\"token comment\">\/\/ src\/utils.js<\/span><br \/>\n<span class=\"token keyword\">function<\/span> <span class=\"token function\">generateId<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">length <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">8<\/span><\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">const<\/span> chars <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#039;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789&#039;<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">let<\/span> result <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#039;&#039;<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">let<\/span> i <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span> i <span class=\"token operator\">&lt;<\/span> length<span class=\"token punctuation\">;<\/span> i<span class=\"token operator\">&#043;&#043;<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        result <span class=\"token operator\">&#043;&#061;<\/span> chars<span class=\"token punctuation\">.<\/span><span class=\"token function\">charAt<\/span><span class=\"token punctuation\">(<\/span>Math<span class=\"token punctuation\">.<\/span><span class=\"token function\">floor<\/span><span class=\"token punctuation\">(<\/span>Math<span class=\"token punctuation\">.<\/span><span class=\"token function\">random<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> chars<span class=\"token punctuation\">.<\/span>length<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> result<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token keyword\">function<\/span> <span class=\"token function\">formatTime<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">timestamp<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">Date<\/span><span class=\"token punctuation\">(<\/span>timestamp<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">toISOString<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>module<span class=\"token punctuation\">.<\/span>exports <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span> generateId<span class=\"token punctuation\">,<\/span> formatTime <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<hr \/>\n<h3>8. \u90e8\u7f72\u4e0e\u6d4b\u8bd5<\/h3>\n<h4>8.1 \u672c\u5730\u8fd0\u884c<\/h4>\n<p><span class=\"token comment\"># \u5b89\u88c5\u4f9d\u8d56<\/span><br \/>\n<span class=\"token function\">npm<\/span> <span class=\"token function\">install<\/span><\/p>\n<p><span class=\"token comment\"># \u542f\u52a8\u670d\u52a1\u5668<\/span><br \/>\n<span class=\"token function\">npm<\/span> start<\/p>\n<p><span class=\"token comment\"># \u5f00\u53d1\u6a21\u5f0f (\u81ea\u52a8\u91cd\u542f)<\/span><br \/>\n<span class=\"token function\">npm<\/span> run dev<\/p>\n<h4>8.2 \u6d4b\u8bd5\u6b65\u9aa4<\/h4>\n<p>1. \u542f\u52a8\u4fe1\u4ee4\u670d\u52a1\u5668<br \/>\n   npm start<\/p>\n<p>2. \u542f\u52a8\u9759\u6001\u6587\u4ef6\u670d\u52a1\u5668 (\u5ba2\u6237\u7aef)<br \/>\n   cd client<br \/>\n   npx http-server -p 3000<\/p>\n<p>3. \u6253\u5f00\u4e24\u4e2a\u6d4f\u89c8\u5668\u7a97\u53e3<br \/>\n   http:\/\/localhost:3000<\/p>\n<p>4. \u4e24\u4e2a\u7a97\u53e3\u8f93\u5165\u76f8\u540c\u7684\u623f\u95f4 ID<br \/>\n   \u70b9\u51fb&#034;\u52a0\u5165\u623f\u95f4&#034;<\/p>\n<p>5. \u5141\u8bb8\u6444\u50cf\u5934\/\u9ea6\u514b\u98ce\u6743\u9650<\/p>\n<p>6. \u89c2\u5bdf\u89c6\u9891\u901a\u8bdd\u662f\u5426\u5efa\u7acb<\/p>\n<h4>8.3 \u751f\u4ea7\u90e8\u7f72<\/h4>\n<p><span class=\"token comment\">\/\/ \u4f7f\u7528 HTTPS (\u751f\u4ea7\u73af\u5883\u5fc5\u9700)<\/span><br \/>\n<span class=\"token keyword\">const<\/span> https <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">require<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;https&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token keyword\">const<\/span> fs <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">require<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;fs&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token keyword\">const<\/span> server <span class=\"token operator\">&#061;<\/span> https<span class=\"token punctuation\">.<\/span><span class=\"token function\">createServer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token literal-property property\">cert<\/span><span class=\"token operator\">:<\/span> fs<span class=\"token punctuation\">.<\/span><span class=\"token function\">readFileSync<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;\/path\/to\/cert.pem&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token literal-property property\">key<\/span><span class=\"token operator\">:<\/span> fs<span class=\"token punctuation\">.<\/span><span class=\"token function\">readFileSync<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;\/path\/to\/key.pem&#039;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ \u4f7f\u7528 wss:\/\/ \u8fde\u63a5<\/span><br \/>\n<span class=\"token keyword\">const<\/span> wss <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">WebSocket<span class=\"token punctuation\">.<\/span>Server<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span> server <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<hr \/>\n<h3>9. \u603b\u7ed3<\/h3>\n<h4>9.1 \u6838\u5fc3\u8981\u70b9<\/h4>\n<table>\n<tr>\u7ec4\u4ef6\u529f\u80fd<\/tr>\n<tbody>\n<tr>\n<td>WebSocket<\/td>\n<td>\u5b9e\u65f6\u53cc\u5411\u901a\u4fe1<\/td>\n<\/tr>\n<tr>\n<td>RoomManager<\/td>\n<td>\u623f\u95f4\u521b\u5efa\/\u52a0\u5165\/\u79bb\u5f00<\/td>\n<\/tr>\n<tr>\n<td>MessageHandler<\/td>\n<td>\u4fe1\u4ee4\u6d88\u606f\u8def\u7531<\/td>\n<\/tr>\n<tr>\n<td>\u5ba2\u6237\u7aef<\/td>\n<td>PeerConnection \u7ba1\u7406<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>9.2 \u6269\u5c55\u5efa\u8bae<\/h4>\n<p>\u53ef\u6269\u5c55\u529f\u80fd:<br \/>\n1. \u7528\u6237\u8ba4\u8bc1 (JWT)<br \/>\n2. \u623f\u95f4\u5bc6\u7801<br \/>\n3. \u5c4f\u5e55\u5171\u4eab<br \/>\n4. \u6587\u5b57\u804a\u5929<br \/>\n5. \u5f55\u5236\u529f\u80fd<br \/>\n6. Redis \u96c6\u7fa4\u652f\u6301<\/p>\n<h4>9.3 \u4e0b\u4e00\u7bc7\u9884\u544a<\/h4>\n<p>\u5728\u4e0b\u4e00\u7bc7\u6587\u7ae0\u4e2d,\u6211\u4eec\u5c06\u6df1\u5165\u63a2\u8ba8 SFU \u67b6\u6784\u3002<\/p>\n<hr \/>\n<h3>\u53c2\u8003\u8d44\u6599<\/h3>\n<li>ws &#8211; WebSocket library<\/li>\n<li>WebRTC API<\/li>\n<hr \/>\n","protected":false},"excerpt":{"rendered":"<p>\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218) \u672c\u6587\u662f WebRTC \u7cfb\u5217\u4e13\u680f\u7684\u7b2c\u4e8c\u5341\u4e00\u7bc7,\u5c06\u624b\u628a\u624b\u6559\u4f60\u4f7f\u7528 Node.js \u6784\u5efa\u4e00\u4e2a\u5b8c\u6574\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668,\u5305\u62ec WebSocket \u901a\u4fe1\u3001\u623f\u95f4\u7ba1\u7406\u548c Offer\/Answer \u4ea4\u6362\u3002 \u76ee\u5f55<br \/>\n\u4fe1\u4ee4\u670d\u52a1\u5668\u6982\u8ff0\u9879\u76ee\u7ed3\u6784WebSocket \u670d\u52a1\u5668\u623f\u95f4\u7ba1\u7406\u4fe1\u4ee4\u6d88\u606f\u5904\u7406\u5ba2\u6237\u7aef\u5b9e\u73b0\u5b8c\u6574\u4ee3\u7801\u90e8\u7f72\u4e0e\u6d4b\u8bd5\u603b\u7ed3 1. \u4fe1\u4ee4\u670d\u52a1\u5668\u6982\u8ff0<br \/>\n1.1 \u4fe1\u4ee4\u670d\u52a1\u5668\u7684\u4f5c\u7528<br \/>\n\u4fe1\u4ee4\u670d\u52a1\u5668\u804c\u8d23:1. \u7528\u6237\u7ba1\u7406- \u7528\u6237\u8fde\u63a5\/\u65ad\u5f00- \u7528\u6237<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[186,537,43],"topic":[],"class_list":["post-65157","post","type-post","status-publish","format-standard","hentry","category-server","tag-node-js","tag-webrtc","tag-43"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218) - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/65157.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218) - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218) \u672c\u6587\u662f WebRTC \u7cfb\u5217\u4e13\u680f\u7684\u7b2c\u4e8c\u5341\u4e00\u7bc7,\u5c06\u624b\u628a\u624b\u6559\u4f60\u4f7f\u7528 Node.js \u6784\u5efa\u4e00\u4e2a\u5b8c\u6574\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668,\u5305\u62ec WebSocket \u901a\u4fe1\u3001\u623f\u95f4\u7ba1\u7406\u548c Offer\/Answer \u4ea4\u6362\u3002 \u76ee\u5f55 \u4fe1\u4ee4\u670d\u52a1\u5668\u6982\u8ff0\u9879\u76ee\u7ed3\u6784WebSocket \u670d\u52a1\u5668\u623f\u95f4\u7ba1\u7406\u4fe1\u4ee4\u6d88\u606f\u5904\u7406\u5ba2\u6237\u7aef\u5b9e\u73b0\u5b8c\u6574\u4ee3\u7801\u90e8\u7f72\u4e0e\u6d4b\u8bd5\u603b\u7ed3 1. \u4fe1\u4ee4\u670d\u52a1\u5668\u6982\u8ff0 1.1 \u4fe1\u4ee4\u670d\u52a1\u5668\u7684\u4f5c\u7528 \u4fe1\u4ee4\u670d\u52a1\u5668\u804c\u8d23:1. \u7528\u6237\u7ba1\u7406- \u7528\u6237\u8fde\u63a5\/\u65ad\u5f00- \u7528\u6237\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/65157.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-01-24T07:40:44+00:00\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/65157.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/65157.html\",\"name\":\"\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218) - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-01-24T07:40:44+00:00\",\"dateModified\":\"2026-01-24T07:40:44+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/65157.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/65157.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/65157.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218) - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/65157.html","og_locale":"zh_CN","og_type":"article","og_title":"\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218) - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218) \u672c\u6587\u662f WebRTC \u7cfb\u5217\u4e13\u680f\u7684\u7b2c\u4e8c\u5341\u4e00\u7bc7,\u5c06\u624b\u628a\u624b\u6559\u4f60\u4f7f\u7528 Node.js \u6784\u5efa\u4e00\u4e2a\u5b8c\u6574\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668,\u5305\u62ec WebSocket \u901a\u4fe1\u3001\u623f\u95f4\u7ba1\u7406\u548c Offer\/Answer \u4ea4\u6362\u3002 \u76ee\u5f55 \u4fe1\u4ee4\u670d\u52a1\u5668\u6982\u8ff0\u9879\u76ee\u7ed3\u6784WebSocket \u670d\u52a1\u5668\u623f\u95f4\u7ba1\u7406\u4fe1\u4ee4\u6d88\u606f\u5904\u7406\u5ba2\u6237\u7aef\u5b9e\u73b0\u5b8c\u6574\u4ee3\u7801\u90e8\u7f72\u4e0e\u6d4b\u8bd5\u603b\u7ed3 1. \u4fe1\u4ee4\u670d\u52a1\u5668\u6982\u8ff0 1.1 \u4fe1\u4ee4\u670d\u52a1\u5668\u7684\u4f5c\u7528 \u4fe1\u4ee4\u670d\u52a1\u5668\u804c\u8d23:1. \u7528\u6237\u7ba1\u7406- \u7528\u6237\u8fde\u63a5\/\u65ad\u5f00- \u7528\u6237","og_url":"https:\/\/www.wsisp.com\/helps\/65157.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-01-24T07:40:44+00:00","author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"11 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/65157.html","url":"https:\/\/www.wsisp.com\/helps\/65157.html","name":"\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218) - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-01-24T07:40:44+00:00","dateModified":"2026-01-24T07:40:44+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/65157.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/65157.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/65157.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"\u6784\u5efa\u81ea\u5df1\u7684 WebRTC \u4fe1\u4ee4\u670d\u52a1\u5668 (Node.js \u5b9e\u6218)"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/65157","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=65157"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/65157\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=65157"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=65157"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=65157"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=65157"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}