
最近在学校,我终于有这么一段时间可以支配,所以我的心仍然很酸和舒服. 当然,也有罪恶的事情. 例如,我一个星期没吃早餐了. 实际上,如果我现在回头看,我真的不会怪我,因为最近的天气太糟糕了!冷!现在!好吧,为了减少内the感,最好学习(diǎn)东(shì)西(qing). 停止胡说八道,或转到主题.
对于这个丑陋而无与伦比的,暂时在他的背上添加一个“ v1.0”. 毕竟,没有迭代. 编写后,将直接释放它. 当然,有很多地方可以弄乱,例如:
实际上,还有很多想象空间.
在编写此演示时,我在写作的同时也在学习. 这些学习资料主要是由Liu Wayong的Node.js + Web Socket创建的,用于创建即时聊天程序,嗨聊天,主流搜索引擎以及我的最爱. 补充了技术社区SegmentFault.
源代码已上传到我的github,克隆到本地后,在终端中运行以下两个命令:
npm install
node server
然后打开浏览器并访问localhost,您可以在不连接Internet的情况下观看此演示.
输入用户名以完成登录
然后您就可以开始与人聊天
当然,Node.js是必不可少的,这里推荐两个很棒的Node.js教程:
Node.js只需几行代码即可实现服务器
var http = require('http');
http.createServer(function(request, response){
response.writeHead(200, {'Content-type':'text/plain'});
response.write('Hey you, my name is kyrieliu~');
response.end();
}).listen(8080);
在终端中执行此代码时,请访问: 8080,您会看到一行: 嘿,我叫kyrieliu〜
这意味着您的节点服务已设置. Asi,js编写背景逻辑,用脚尖思考,这将是一件很酷的事情
此外,使用了两个软件包模块:
express是用于在node.js中管理路由响应请求的模块,并根据请求的URL返回相应的HTML页面. 在这里,我们使用预先编写的静态页面返回到客户端,只需使用express来指定要返回的页面的路径. 如果您不使用此程序包,则需要一起编写HTML代码和后台JavaScript代码以响应请求,这很不方便.
socket.io封装了websocket,还包括其他连接方法,例如Ajax. 原因是并非所有浏览器都支持websocket. 通过socket.io包,您无需关心其中使用了哪种连接方法. 您可以在任何浏览器中使用socket.io建立异步连接.
乍一看,界面就像chǒu(lòu)一样简单,但是“麻雀虽小,但具有所有内部器官”,您仍然应该拥有一些东西. 在这里,您可以直接粘贴DOM结构.
<div class="container chat-container">
<!-- 标题展示信息 -->
<div class="row"></div>
<!-- 历史消息 -->
<div class="row">
<div class="col-md-6 col-md-offset-3 col-sm-12 historyMsg" id="historyMsg"></div>
</div>
<!-- 控制台 -->
<div class="row">
<div class="col-md-6 col-md-offset-3 col-sm-12 control">
<div class="row control-row"></div>
</div>
</div>
<!-- 遮罩层 -->
<div id="loginWrapper" class="loginWrapper"></div>
</div>
直接看笔记,您可以清楚地看到小麻雀的“”,“肝脏”,“脾脏”和“肺部”. (“肾脏”呢?嗯,你觉得我的新手机是怎么来的?)
关于那些辛辣的眼睛的类名,是因为在项目中使用了Bootstrap,这被认为是懒惰的.

完成UI后,请考虑如何在此中实现交互.
“您不是那样说的,请使用websocket. ”
这句话不是假的,但是这里我指的是互动. 毕竟,如果您编写一个程序,那么您必须对程序中的逻辑“批判”(我是这个成语)
考虑一下,好像有那么多,然后开始一一打破
请注意,由于它是聊天系统,因此与服务器建立连接的方式与通常不同. 这里使用的协议是HTTP WebSocket,用于实现持久连接.
一个简短的解释,这里的“持久”是相对于HTTP的“非持久”协议(您的意思是HTTP的女士会羡慕WebSocket的女士).
通过阅读Ovear对Zhihu的回答,让我们谈谈这两种协议之间的区别.
HTTP的生命周期可能是这样的. 一个请求和一个响应,这个请求结束了; HTTP 1.1已得到改进,并添加了保持活动状态. 效果是,在此HTTP连接中,可以发送它. 多个请求接受多个响应,但从本质上讲,请求=响应手机网页,也就是说,请求和响应始终是一一对应的,当没有请求时,服务器无法主动响应.
客户端和服务器完成协议升级(HTTP-> WebSocket)后,建立了持久连接,连接持续多长时间?该连接可以一直持续到客户端或服务器之一主动关闭连接. HTTP的最大区别在于服务器此时可以主动将消息推送到客户端. 在这个项目中,我们使用socket.io包模块来实现WebSocket. Socket.io不仅封装WebSocket,而且还封装了通用接口以及Ajax轮询和其他实时通信方法. 这样做的原因是,当服务器不支持WebSocket时,可以将其转换为其他实现方法,可以称为放纵柔滑
下一步是实现部分. 在前端引入socket.io.js文件后该怎么办?
对话很便宜,请向您显示代码.
var socket = io.connect();
是的,就是这么简单,不要相信您会去看官方文档.
此处的“登录”不是真实的登录名. 执行io.connect()时,即使已建立连接,也要处理一些交互.
监视前端的连接事件. 此事件的触发条件是: 与服务器成功建立连接.
socket.on('connect',function(){
//do something
});
该回调包含此时要完成的DOM操作,例如:
更改提示文本(最初为“正在连接服务器...”)
显示覆盖层
关注文本框
当用户输入昵称并单击“登录”按钮时,当前套接字将触发服务器的登录事件:
socket.emit('login',nickname);
携带一个参数,这是用户输入的昵称.

服务器检查昵称的有效性时,将在其通过时触发:
socket.on('loginSuccess', function(){
//1. 隐藏登录层
//2. 用户可以愉快和别人聊天了~
});
如果用户输入的昵称不合法,请触发:
socket.on('loginFailed', function(){
//1. 提示用户昵称哪里出问题了
//2. 等待用户重新输入
});
请注意,这里的事件名称(例如login,loginSuccess和loginFailed)都是可自定义的,只要它们与服务器一致就可以.
想象一下向用户发送消息的操作,将其分解: 输入文本->单击发送. 就是这样,好的. 在这里,您需要在“发送”按钮上挂起一个事件,并告诉服务器: “服务器端服务器,这里是套接字XXX,我给您发送了一条消息,请注意检查是否结束. ”
socket.emit('msgSend',msg);
携带一个参数,即用户输入.
在接收消息的逻辑中有三种情况
您自己发送的消息
其他人发送的消息
系统提示信息
魔潘,一一.
您发送的消息直接显示在聊天消息面板上. 您无需与后台进行交互即可接收您发送的消息. 您只需要告诉我我已将此消息发送给所有人的背景即可. 当然,您也可以使用微信来处理发送的消息: 发送时将消息添加到聊天面板中->放置小菊花或在旁边加载->与背景交互->隐藏菊花;失败会将小菊花变成红色的感叹号,表明用户发送失败.
现在,您需要在前端设置一个监视事件,以响应来自服务器的“新消息”.
socket.on('newMsg', function(nickname, msg){
//显示这条新消息
});
回调函数中有两个参数,昵称和msg,它们是消息发件人的昵称和消息内容. 这两个是怎么来的?不用担心,我们稍后将在服务器逻辑中进行讨论. 在这里,您只需要知道在前端接收新消息时,这两个参数是必需的,因为它们涉及显示新消息.
有关系统的提示信息主要分为两个:
提示新用户加入和退出
显示当前用户数
看起来像这样手机网页,所以您需要监视前端的系统事件

socket.on('system', function(nickname, count, type){
//1.根据系统事件类型(新加入或离开)来提示用户
//2.修改用户数量
});
这里的三个参数也是必不可少的. 昵称代表触发系统事件的用户的昵称,计数代表当前的用户数,类型代表事件的类型(加入/离开). 同样,这三个参数也是从服务器传递的.
对应前端,后台的逻辑主要分为以下几部分
启动服务
建立连接
用户登录
接受用户发送的消息并进行广播
系统消息处理
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
app.use('/',express.static(__dirname + "/www"));
server.listen(8080);
因为我将前端文件(html / js / css)放在了www文件夹中,所以我使用express来指定返回到浏览器的页面的路径.
当然,除了express之外,我们还需要引入socket.io模块并将其绑定到服务器.
服务已启动,如何建立连接?
io.on('connection', function(socket){
//do something
});
就……这个...?
Ang.
您没看错,但我没有写错,这对应于前端逻辑:
var socket = io.connect();
socket.on('connect', function(){
//do something
});
建立连接后,可以编写有关套接字活动的所有逻辑. (仅供参考: 它是写在此连接事件的回调中的)
还记得前端触发的登录事件是什么?
socket.emit('login', nickname);
这称为登录,它还带有一个参数-用户想要给自己的昵称. 好的,让我们写相应的背景逻辑
socket.on('login', function(nickname){
//do something
});

这里做什么?那是为了验证用户输入的昵称是否合法,例如该昵称是否已经存在,长度限制,符号限制等.
球是麻袋,似乎出了点问题...
长度限制和符号限制?这两个伙伴不必在服务器上执行此操作,只需直接在前端上执行. 因此,我们只剩下一个问题-昵称的唯一性.
由于要检查昵称是否唯一,因此必须首先具有当前用户的昵称集合,否则要在哪里检查昵称是否存在?
因此,应在全局范围内维护一个数组,以保存当前用户的昵称
var users = [];
在此数组中查找用户通过登录事件传递的昵称. 如果不存在,则表示当前昵称是合法的,用户可以调用此名称,然后
socket.nickname = nickname;//记录下当前socket的nickname
users.push(nickname);
socket.emit('loginSuccess');//触发loginSuccess事件
如果昵称已经存在,则会触发登录失败事件,并且前端可以进行相应的交互.
socket.emit('loginFailed');
根据约定的事件名称写服务器侦听器
socket.on('msgSend', function(msg){
socket.broadcast.emit('newMsg', socket.nickname, msg);
});
此处调用的API是套接字的广播事件. 效果是将消息广播到当前套接字以外的所有套接字.
剩下的工作是处理系统消息,首先,我们必须弄清楚哪些系统消息可用
用户输入的昵称通过有效性检查后,系统提示新添加的用户
io.sockets.emit('system',nickname, users.length, 'login');
io.sockets.emit()
的作用
用来触发所有当前套接字的事件,这与此处的socket.broadcast.emit()不同.
按照上面的代码,在用户离开时写出广播事件:
io.sockets.emit('system', nickname, users.length, 'logout');
但是在哪里写?目前,您需要在服务器端监视其他断开连接事件
socket.on('disconnect', function(){
var index = users.indexOf(socket.nickname);
users.splice(index, 1);//将断开用户的昵称从全局数组users中删除
io.sockets.emit('system', socket.nickname, users.length, 'logout');
});
在这一点上,即使基于Node.js的完成了,当然还有很多地方可以优化,但这是核心功能. 您可以看到所有这些都是英雄,因为我在写完之后已经看过了. ,感觉就像那位老太太的缠脚长而长
好的,让我们最终做个广告. 我不会说这是什么. 好奇的童鞋会自己扫描〜
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-192769-1.html
别忘了还有大量的女同志
烊烊最棒