Будучи новичком в WebSocket, я нашел много хороших ресурсов в Интернете, большинство из которых содержат отличные демонстрации.
Но демоверсии содержат много кода оптимизации или логического кода, которые служат псевдоцелям демо-приложения. Я думаю, что демонстрация, более похожая на скелет, была бы лучше для новичка? Я пытался сделать это так, и надеюсь, что это может помочь.
Полный источник: https://github.com/JilinXie/ChatRoom
Веб-сокет
Я предполагаю, что у вас есть основное представление о том, что такое WebSocket. Если вы этого не сделаете, это протокол, который позволяет вам общаться из браузера на сервер через TCP.
Демонстрация WebSocket/ws
Прежде чем мы начнем, давайте сделаем демонстрацию, показывающую, как браузер и сервер могут передавать привет через TCP。
Git: https://github.com/JilinXie/ChatRoom/tree/master/WebSocketTut/v1_sayhi
- Сервер:
Мы используем Node.js и WebSocket/ws
npm init npm install --save ws
Запустите указанную выше команду в пустой папке. Мы используем WebSocket/ws lib для сборки сервера. Что может быть так просто, как:
//server.js var WebSocketServer = require('ws').Server; var wss = new WebSocketServer({port: 9090}); wss.on('connection', function(connection) { connection.on('message', function(raw_msg){ console.log(raw_msg); connection.send("world"); } };
Поместите его в server.js и запустите node server.js.
2. Страница клиента:
<!-- client.html --> <script> var signalChannel = new WebSocket("ws://localhost:9090"); signalChannel.onmessage = function(raw_msg) { console.log(raw_msg.data); } signalChannel.onopen = function() { signalChannel.send("hello"); } </script>
Откройте client.html в браузере и откройте консоль:
Вы должны увидеть «world» в консоли браузера и «hello» в выводе узла.
Чат «Протокол»
Давайте определим, как клиент и сервер взаимодействуют (в формате JSON):
- Вход:
Пользователь отправляет операцию входа на сервер. Сервер Храните имя пользователя и его соединение до закрытия соединения. - ListUser:
Когда новый пользователь входит в систему. Сервер должен транслировать его всем. - Разговор:
пользователь может выбрать разговор со «всеми» или с коллегой. Сервер передает информацию.
Login: cli -> server {"operation": "login", "data": {"username": USERNAME(STRING)}} server -> cli {"operation": "login", "data": {"state": STATE(BOOL)}} ListUser: server -> cli {"operation": "listuser", "data": {"usernames": USERNAMES(LIST)}} Talk: cli -> server// if peername is empty, content is broadcasted. {"operation": "talk", "data": {"peername": PEERNAME(STRING), "content": CONTENT(STRING)}} server -> cli {"operation": "talk", "data": {"talker": TALKER(STRING), "content": CONTENT(STRING)}}
Сервер ChatRoom и клиентская среда.
Как показано в «Демонстрации WebSocket/ws», браузер и сервер используют метод «send» и обратный вызов «onmessage» для выполнения связи. Итак, структура нашей клиентской страницы и сервера должна быть примерно такой:
- Страница клиента:
Кстати, мы добавим несколько фиктивных тегов на страницу, которые позже могут содержать содержимое чата.
<!DOCTYPE html> <html> <!-- username shown to other peers --> <label> UserName: </label> <input type="text" id="username"> <button> login </button> <br> <!-- list of all other peers --> <ul id="userlist"> </ul> <!-- peer name to talk to (empty to talk to all) --> <label> PeerName (broadcast if null)</label><input type="text" id="peername"> <br> <!-- chat here --> <textarea id="writeboard" style="width:300px;height:200px;"></textarea> <button> send </button> <br> <!-- board showing other's saying --> <textarea id="chatboard" style="width:300px;height:200px;" readonly></textarea> <script> var signalChannel = new WebSocket("ws://localhost:9090"); signalChannel.onmessage = function(raw_msg) { let msg = {}; try { msg = JSON.parse(raw_msg.data); } catch(e) { console.log("Invalid msg format"); return; } switch (msg.operation) { case "login": //handle login; break; case "listuser": //handle list user; break; case "talk": //handle talk; break; default: break; } } </script> </html> </html>
2. Как выглядит сервер.
var WebSocketServer = require('ws').Server; var wss = new WebSocketServer({port: 9090}); wss.on('connection', function(connection) { connection.on('message', function(raw_msg) { let msg = {}; try { msg = JSON.parse(raw_msg); } catch(e) { console.log("Invalid message format: " + raw_msg); return; } switch(msg.operation) { case "login": //handle user login //broadcast new user break; case "talk": //handle talk break; default: break; } }); });
Теперь вы можете запустить сервер node server.js
и открыть файл client.html напрямую в браузере.
Внедрите «протокол» ChatRoom
- Используйте JSON
Все сообщения, отправляемые клиентами и сервером, имеют формат JSON.
клиент
function sendMsg(msg) { signalChannel.send(JSON.stringify(msg)); }
сервер
function sendMsg(connection, msg) { connection.send(JSON.stringify(msg)); }
2. Войти
Каждый клиент установил соединение с сервером после загрузки страницы, на var wss = new WebSocketServer({port: 9090});
. По логину сервер привязывал соединение с никнеймом.
клиент
<button onclick="login()"> login </button> ...... function login() { let username = document.getElementById("username").value; let command = {operation: "login", data: {username: username}}; sendMsg(command); } ...... switch (msg.operation) { case "login": login(); break; ... }
сервер
var users_db = {}; function login(connection, username) { users_db[username] = connection; } ....... switch(msg.operation) { case "login": login(connection, msg.data.username); break; ...... }
3. сервер userlist
, транслирует список имен пользователей всем остальным.
function broadcast_newuser() { let usernames = Object.keys(users_db); for (let username in users_db) { sendMsg(users_db[username], {operation: "listuser", data: {usernames: usernames}}); } }
клиент, получить и обновить список пользователей ‹ul›
function update_userlist(usernames) { let userlist = document.getElementById("userlist"); userlist.innerHTML = ""; for (let i in usernames) { userlist.innerHTML += "<li>" + usernames[i] + "</li>"; } } ...... switch(msg.operation) { ...... case "listuser": update_userlist(msg.data.username); break; ...... }
И теперь вы можете запустить node server.js
и открыть несколько client.html в своем браузере, войти на каждую страницу с другим именем. Они увидятся в ‹ul›.
4. Обсуждение
Итак, это последний шаг к тому, чтобы сделать этот материал немного полезным. Заставьте их обмениваться сообщениями через сервер.
Здесь мы поместим только реализацию трансляции.
клиент
<button onclick="talk()"> send </button> ...... function talk() { let text = document.getElementById("writeboard").value; if (text === "") { alert("nothing to send"); return; } let command = {operation: "talk", data: {peername: '', content: text}} document.getElementById("writeboard").value = ""; sendMsg(command); } ...... function update_chatboard(content, username) { let chatboard = document.getElementById("chatboard"); chatboard.value += username + ": " + content + '\n'; } switch(msg.operation) { ...... case "talk": update_chatboard(msg.data.content, msg.data.talker); break; }
server
При получении голосового сообщения от клиента транслируйте сообщение и имя пользователя всем клиентам.
function _who_am_i(connection) { for (let uname in users_db) { if (connection.id === users_db[uname].id) { return uname; } } return '----'; } function broadcast_talk(content, talker) { for (let username in users_db) { sendMsg(users_db[username], {operation: "talk", data: {content: content, talker: talker}}) } } ...... switch(msg.operation) { ...... case "talk": broadcast_talk(msg.data.content, _who_am_i(connection)) break; ...... }
Теперь вы можете общаться между клиентами
Вы можете проверить https://github.com/JilinXie/ChatRoom/tree/master/WebSocketTut/v2_talk
, чтобы получить код.
/> Где client_frame.html и server_frame.js — это источник ChatRoom Server and Client Framework, а client.html и server.js — это источник реализации протокола чата.
Ну наконец то:
Приведенный здесь код предназначен для иллюстрации основных вещей, которые помогут новичкам разобраться. Я пытался избавиться от логики, не связанной с websocket.
Но вы можете проверить https://github.com/JilinXie/ChatRoom для оптимизированной версии.
Ура~ Я опубликовал свою первую статью :D.