webSocket 简介
WebSocket 是 html5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议.
WebSocket 使得客户端和服务器之间的数据交换变得更加简单, 允许服务端主动向客户端推送数据. 在 WebSocket API 中, 浏览器和服务器只需要完成一次握手, 两者之间就直接可以创建持久性的连接, 并进行双向数据传输.
在 WebSocket API 中, 浏览器和服务器只需要做一个握手的动作, 然后, 浏览器和服务器之间就形成了一条快速通道. 两者之间就直接可以数据互相传送.
为什么传统的 HTTP 协议不能做到 WebSocket 实现的功能? 这是因为 HTTP 协议是一个请求 - 响应协议, 请求必须先由浏览器发给服务器, 服务器才能响应这个请求, 再把数据发送给浏览器. 换句话说, 浏览器不主动请求, 服务器是没法主动发数据给浏览器的.
Web
我们先用 express 搭一个基础的服务端.
创建 index.JS 文件
- var App = require('express')();
- var http = require('http').createServer(App);
- App.get('/', function(req, res){
- res.send('<h1>Hello world</h1>');
- });
- http.listen(3000, function(){
- console.log('listening on *:3000');
- });
run node index.JS, 并在浏览器打开 http://localhost:3000, 访问成功即可看到
HTML
设计我们的主页, 实现一个简单的聊天窗口.
修改 index.JS
- App.get('/', function(req, res){
- res.sendFile(__dirname + '/index.html');
- });
创建 index.HTML
- <!doctype HTML>
- <HTML>
- <head>
- <title>
- Socket.IO chat
- </title>
- <style>
- * { margin: 0; padding: 0; box-sizing: border-box; } body { font: 13px
- Helvetica, Arial; } form { background: #000; padding: 3px; position: fixed;
- bottom: 0; width: 100%; } form input { border: 0; padding: 10px; width:
- 90%; margin-right: .5%; } form button { width: 9%; background: rgb(130,
- 224, 255); border: none; padding: 10px; } #messages { list-style-type:
- none; margin: 0; padding: 0; } #messages li { padding: 5px 10px; } #messages
- li:nth-child(odd) { background: #eee; }
- </style>
- </head>
- <body>
- <ul id="messages">
- </ul>
- <form action="">
- <input id="m" autocomplete="off" />
- <button>
- Send
- </button>
- </form>
- </body>
- </HTML>
重启应用并刷新页面你就可以看到一个如下图所示
Socket.io
引入 socket.io
NPM install --save socket.io
修改 index.JS
- var App = require('express')();
- var http = require('http').Server(App);
- var io = require('socket.io')(http);
- App.get('/', function(req, res){
- res.sendFile(__dirname + '/index.html');
- });
- io.on('connection', function(socket){
- console.log('an user connected');
- });
- http.listen(3000, function(){
- console.log('listening on *:3000');
- });
修改 index.HTML, 在 </body > 下添加如下代码
- <script src="/socket.io/socket.io.js"></script>
- <script>
- var socket = io();
- </script>
重启应用并刷新页面, 就可以看到命令行打印如下
Emitting event
当用户在聊天窗的输入框内输入, 并提交时, 触发 emit 事件, 服务端监听到该事件并做出相应的反应.
修改 index.HTML
- <script src="/socket.io/socket.io.js"></script>
- <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
- <script>
- $(function () {
- var socket = io();
- $('form').submit(function(e){
- e.preventDefault(); // 防止页面重新加载
- socket.emit('chat message', $('#m').val());
- $('#m').val('');
- return false;
- });
- });
- </script>
服务端监听该事件, 在 index.JS 文件添加该代码
- io.on('connection', function(socket){
- socket.on('chat message', function(msg){
- console.log('message:' + msg);
- });
- });
展示消息
当服务端收到用户 A 发出的消息, 服务端重新发出该消息, 让客户端接收, 客户端监听到该事件后展示该条消息, 就可以实现用户 A, B, C 都接收到该消息.
修改 index.JS
- io.on('connection', function(socket){
- socket.on('chat message', function(msg){
- io.emit('chat message', msg);
- });
- });
修改 index.HTML, 实现消息的展示
- <script>
- $(function () {
- var socket = io();
- $('form').submit(function(e){
- e.preventDefault(); // prevents page reloading
- socket.emit('chat message', $('#m').val());
- $('#m').val('');
- return false;
- });
- socket.on('chat message', function(msg){
- $('#messages').append($('<li>').text(msg));
- });
- });
- </script>
重启应用并刷新页面, 可以打开多个浏览器页面同时访问 localhost:3000, 就可以体验简单聊天室的效果.
设置昵称
在每个用户进入的时候, 随机生成一个数字作为用户的昵称, 并且向所有用户广播该用户进入聊天室. 当用户发送消息时, 拼接上用户的昵称.
修改 index.JS
- io.on('connection', (socket) => {
- const nickname = 'user' + Math.ceil((Math.random() * 1000))
- socket.broadcast.emit('connection', nickname + 'connected')
- socket.on('chat message', (msg) => {
- io.emit('chat message', nickname + ':' + msg)
- })
- })
修改 index.HTML, 监听 connection 事件
- <script>
- $(() => {
- const socket = io()
- $('form').submit((e) => {
- e.preventDefault()
- socket.emit('chat message', $('#m').val())
- $('#m').val('')
- return false
- });
- socket.on('chat message', (msg) => {
- $('#messages').append($('<li>').text(msg))
- })
- socket.on('connection', (msg) => {
- $('#messages').append($('<li>').text(msg))
- })
- });
- </script>
重启应用并打开多个客户端, 可以看到如下效果
参考资料
本文大部分案例出自 socket.io 的入门文档 https://socket.io/get-started/chat/
https://en.wikipedia.org/wiki/WebSocket
廖雪峰官网 WebSocket
菜鸟教程 WebSocket http://www.runoob.com/html/html5-websocket.html
来源: https://www.cnblogs.com/chaohangz/p/10745489.html