前端小Demo:使用Socket实现简易网络聊天室
Posted 我是真的不会前端
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端小Demo:使用Socket实现简易网络聊天室相关的知识,希望对你有一定的参考价值。
项目实现截图
1.实现原理
websocket
首先我们要知道 http是一种无状态协议,无法轻松实现实时应用。服务器只会响应来自客户端的请求,但是它与客户端之间不具备持续连接。我们可以实现捕获浏览器上的事件,通过事件跟服务器进行数据交互,使用ajax技术。但是反过来却不可能实现:服务器发生了一个事件,服务器不会主动去跟客户端交互。你们想一想,如果有一天百度像你发送了一个请求,会不会觉得很诡异。
可是聊天室确实存在。聊天室是要保持客户端和服务器持续连接,且服务器能主动给客户端发送消息,实现方式如下:
长轮询:
客户端每隔很短的时间,当时通过setinterval每隔多少秒都会对服务器发出请求,查看是否有新的消息,只要轮询速度足够快,就能给人造成交互是实时进行的感觉。这种做法实属无奈,实际上会对服务器、客户端双方都造成了大量的性能浪费。
长连接:
客户端跟服务器连接一次,连接上之后就不断开,服务器不给客户端响应,服务器有了新数据就将数据发回去,又有了新数据,就将数据发回来,而一直保持阻塞状态。这种做法也会造成大量的性能浪费。
H5提供了一个新技术解决这些问题:websocket
websocket协议能够让浏览器和服务器进行全双工实时通信,全双工就是互相之间都能主动发送消息了,服务器也能主动给客户端发送消息。
websocket的原理:
利用http请求产生握手,http头部中含有websocket协议的请求,所以握手之后,二者转用tcp协议进行交流,tcp是一个比较底层的协议,可以实现实时通信。现在的qq使用的就是这个协议。
所以websocket协议需要浏览器支持,也需要服务器支持。
支持websocket协议的浏览器:Chrome4、FireFox4、Safari5
支持websocket协议的服务器:Node0、Apache7.0.2、nginx1.3
可以看出,nodejs天生就支持websocket协议,但是从底层一步一步搭建nodejs服务器来处理tcp协议的工程是很庞大的,所以现在有一个通用的第三方模块来处理websocket - socket.io
socket.io
如何下载
npm i socket.io -S
官网
http://socket.io/
2.socket搭建
搭建一个聊天室:
1.创建一个web服务器
const http = require('http')
const server = http.createServer((req,res)=>{
res.setHeader('content-type','text/html;charset=utf8')
res.end("这是web服务器")
})
server.listen(3000)
2.接下来导入socket.io
并通过socket.io将web服务器转换成一个长连接服务器,且将客户端需要一个js文件路径暴露出去:
const socketIO = require('socket.io')
const io = socketIO(server)
此时,我们通过服务器就能访问到一个地址:http://locahost:3000/socket.io/socket.io.js
,最终能响应得到一个js文件地址。
客户端通过这个地址就能跟服务器进行即时通信了。
客户端代码:
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io()
</script>
3.有关socket对象
客户端导入的这个js文件中,暴露了io函数,调用得到一个socket对象。
socket其实一个套接字,类似于插座,此时服务器有一个插座,客户端有一个插头,只要能将两边连接在一起就能进行通信了。
得到的socket这个套接字对象,他的使用方法是使用事件的机制:
socket对象有一个emit方法,用来触发事件 - 发送消息
socket对象有一个on方法,来绑定事件 - 监听是否消息接收到
// 接收消息
socket.on('message',message=>{
// 监听message事件,只要对方触发了message事件,message就是对方发送过来的数据
console.log(message)
})
// 发送消息
socket.emit('send',数据) // 表示触发了事件send,并在触发事件的时候将数据传送了过去
4.服务器的操作:
我们创建好的io对象需要绑定一个固定的事件 - connection,如果有客户端连接过来,就会触发这个事件
io.on('connection',socket=>{
// 有客户端连接来,会得到一个socket对象,这个socket跟客户端的socket是同一个,就表示插头和插座连接在一起了,所有这个socket也可以进行绑定事件和触发事件
// 通信
socket.emit('message',数据)
socket.on('send',数据)
})
上面的message事件和send事件都是自定义的,不是固定的,且客户端和服务器进行交互的时候,使用的都是js,所以他们之间进行交互的数据,只要符合js的数据类型就能进行,比如字符串、数字、对象、数组 。。。
此时只是实现了一个客户端和一个服务器之间的即时通信,如果要多个客户端和一个服务器进行通信的话,还需要服务器将数据进行广播:
io.emit('message',数据)
服务器进行相应的时候,不能只用socket进行发送数据,需要使用io,就代表所有客户端了。
3.项目代码
服务器模块
这里需要创建nodejs服务器,导入socket.io模块 暴露websocket函数
// 1.创建http服务器 - websocket是隐藏在http请求中的
const http = require('http')
const fs = require('fs')
const server = http.createServer((req,res)=>{
let url = req.url;
if(url === '/'){
let data = fs.readFileSync('index.html')
res.end(data)
}
})
// 2.导入socket.io模块
const socketIo = require('socket.io')
// 3.将websocket暴露出来
const io = socketIo(server) // 将web服务器当做参数传进去
// 有了这行代码,就暴露有一个js文件的地址:/socket.io/socket.io.js - 用于个客户端使用的
// io这个对象可以绑定一个connect事件,表示有客户端连接过来
io.on('connect',function(socket){ // 这里的socket其实跟客户端使用的socket是同一个socket
// socket可以用来接收客户端的请求 - 监听指定的事件名称
socket.on('fasong',function(message){ // message其实就是客户端发送过来的消息
// 接收到任意一个客户端发来的消息 - 需要将消息进行广播 - 给所有客户端发送消息
// 使用io来触发事件,就是在广播消息
io.emit('send',message)
})
// 服务器也可以给客户端发消息 - 给刚刚发消息过来的客户单回复消息
})
server.listen(3000)
创建socket服务端
原理
通过登入,保存用户名到coockie。如果url是/login。响应登入页面。设置两小时coockie时间。发现coockie存在 响应聊天界面。获取coockie响应对方的用户名,发送一个对象进去:其中包括username msg id:socket id
代码
const http = require('http')
const fs = require('fs')
// 获取cookie的方法
let getCookie = (cookies,key)=>{
let arr = cookies.split('; ')
for(let i=0;i<arr.length;i++){
let brr = arr[i].split('=')
if(brr[0] === key){
return brr[1]
}
}
}
const server = http.createServer((req,res)=>{
let url = req.url;
// 判断用户是否登录
// req.headers.cookie
if(url === '/'){
if(req.headers.cookie){
let username = getCookie(req.headers.cookie,'username')
if(!username){
url = '/login'
}else{
let data = fs.readFileSync('./client.html')
res.end(data)
}
}else{
url = '/login'
}
}
if(url === '/login'){
let data = fs.readFileSync('./login.html')
res.end(data)
}
})
// 导入socket.io
const socketIo = require('socket.io')
const io = socketIo(server)
// 监听连接
io.on('connection',function(socket){
// 接收socket的消息
socket.on('request',function(res){
let {message,username} = res
// 广播消息
io.emit('response',{
id:socket.id,
message,
username
})
})
})
// 监听端口
server.listen(3000)
客户端界面
登入界面
代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>document</title>
</head>
<body>
<form action="/logHandler" method="post">
<table>
<tr>
<td>用户名:</td>
<td>
<input type="text" name="username">
</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit">
</td>
</tr>
</table>
</form>
</body>
<script>
document.querySelector('form').onsubmit = function(){
// 设置cookie
let date = new Date()
date.setTime(date.getTime()-6*3600*1000)
document.cookie = 'username='+document.querySelector('[name="username"]').value+";expires="+date+";path=/"
location.href = "/"
return false;
}
</script>
</html>
聊天界面
代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>document</title>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
<textarea name="message" cols="30" rows="10"></textarea>
</body>
<script>
// 发送http包含websocket的请求
// 引入了js文件后,js文件给全局暴露了一个函数 - io
// console.log(io);
// 调用这个函数
let socket = io()
// console.log(socket);
// 调用得到的socket对象,可以个服务器发送消息,也可以接收服务器发过来的消息
// 客户端发消息 - socket.emit(指定事件名,数据)
// socket.emit('fasong','你好啊')
// 发消息放在回车事件中
let textarea = document.querySelector('[name="message"]')
textarea.onkeydown = function(e){
e = e || window.event;
let keycode = e.keyCode || e.which;
if(keycode === 13){
socket.emit('fasong',this.value)
}
}
// 客户端可以监听服务器发来的消息
socket.on('send',function(message){
console.log(message);
})
</script>
</html>
4.完整项目代码
5.如何使用
npm 一键安装组件
拉下来后再所在文件夹打开cmd 命令行输入 npm i 如果报错就使用cnpm i
相关组件安装完成后
然后输入
安装nodemon
命令行输入以下代码
npm i nodemon
nodemon 打开项目
输入
nodemon .\\server.js
浏览器地址栏输入localhost:3000/
效果
进入登入界面随便输入一个用户名
这里以张三李四举例
A浏览器
B浏览器
以上是关于前端小Demo:使用Socket实现简易网络聊天室的主要内容,如果未能解决你的问题,请参考以下文章
第94题JAVA高级技术-网络编程13(简易聊天室8:使用Socket传递图片)
第95题JAVA高级技术-网络编程14(简易聊天室9:使用Socket传递音频)
第92题JAVA高级技术-网络编程11(简易聊天室6:使用Socket通信)