聊天室的原理:客户端A发送消息->服务器接收消息->服务器主动向客户端B发送消息->客户端B接收消息
HTTP请求不适用的原因:客户端/服务端的请求与响应通常基于HTTP协议是实现,但HTTP协议的局限:只能由客户端发送请求,服务器响应请求并返回数据,进行单向的数据传输
WebSocket适用的原因:在单个TCP连接上进行全双工通信的协议。通俗理解:实现客户端/服务端双向数据传输的协议
WebSocket特点:
1.无同源限制,客户端可与任意服务器通信;
2.协议头为ws(wss为加密标识符),如:ws://localhost:8080;
3.目前主流浏览器已支持WebSocket
客户端的实现:
1.创建WebSocket对象,打开WebSocket
var webSocket = new WebSocket(url,[protocal]) //url --- 指定连接的url protocal --- 可接受的子协议
2.触发WebSocket对象的事件,实现连接
webSocket.open = function (){ //同服务器连接时触发
webSocket.send() //向服务器发送数据
}
webSocket.message = function (){ //成功接收到服务器数据时触发
……
}
webSocket.error = function (){ //通信错误时触发
……
}
webSocket.close = function (){ //同服务器连接断开时触发
webSocket.close() //关闭连接
}
Node.js的ws模块实现服务器:
1.导入ws模块,引用Server类,并实例化
const WebSocket = require('ws').Server
wss = new WebSocket({host:'loaclhost',port:8080})
2.调用webSocket对象方法,实现数据传输
wss.on('connection',function(ws){ //连接成功
ws.on('message',function(message){ //接收客户端的数据
client.send() //向客户端发送数据
})
})
具体实现代码:
//入口html文件,确定用户名
<style>
img {
width: 100px;
height: 100px;
border-radius: 50%;
position: absolute;
top: 30%;
left: 50%;
margin-top: -50px;
margin-left: -50px;
}
input {
width: 200px;
border: 1px solid #ccc;
padding: 7px 0px;
border-radius: 3px;
padding-left: 5px;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
position: absolute;
top: 42%;
left: 50%;
margin-left: -100px;
}
input:focus {
border: none;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6)
}
.ant-btn {
line-height: 1.499;
position: relative;
display: inline-block;
font-weight: 400;
white-space: nowrap;
text-align: center;
background-image: none;
border: 1px solid transparent;
box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
cursor: pointer;
transition: all .3s cubic-bezier(.645, .045, .355, 1);
user-select: none;
touch-action: manipulation;
height: 32px;
padding: 0 15px;
font-size: 14px;
border-radius: 4px;
color: rgba(0, 0, 0, 0.65);
background-color: #fff;
border-color: #d9d9d9;
}
.ant-btn-primary {
width: 60px;
color: #fff;
background-color: #1890ff;
border-color: #1890ff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12);
box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
position: absolute;
top: 50%;
left: 50%;
margin-left: -30px;
}
</style>
<body>
<img src="./avatar.jpg" >
<input type="text">
<button class="ant-btn ant-btn-primary" onclick='toChat()' >Go</button>
</body>
<script>
function toChat(){
var name = document.getElementsByTagName('input')[0].value
window.location.href=`./webSocket.html?name=${name}`
}
</script>
//获取url参数
function getQueryString(name) {
let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
let r = window.location.search.substr(1).match(reg);
if (r != null) {
return decodeURIComponent(r[2]);
};
return null;
}
聊天室html文件,用于发送和接收消息
<body>
<div class="chat">
<div class="inputBox">
<input type="text" />
<button class="ant-btn ant-btn-primary" onclick='send()'>发送</button>
</div>
</div>
</body>
<script src='./getUrl.js'></script>
<script>
var user = {
name: getQueryString('name'),
message: [],
}
var flag = true;
var webSocket = new WebSocket("ws://localhost:8080");
function send() {
let value = document.getElementsByTagName('input')[0].value
webSocket.onopen(event, value)
return document.getElementsByTagName('input')[0].value = ''
}
webSocket.onopen = function (event, value) {
if (value == undefined) {
webSocket.send(JSON.stringify(user.name))
return flag = true
} else {
user.message.push(value)
webSocket.send(JSON.stringify(user))
return flag = false
}
}
webSocket.onmessage = function (evt) {
var box = document.createElement("div")
box.setAttribute("class", "box")
//定义头像
var avatar = document.createElement("img")
avatar.src = './avatar.jpg'
var ele = document.createElement("div")
ele.setAttribute("class", "message")
if (flag && typeof JSON.parse(evt.data) == 'string') {
var welcome = document.createElement("div")
welcome.setAttribute('class', 'welcome')
document.body.appendChild(welcome)
welcome.innerHTML = `${JSON.parse(evt.data)}加入聊天室`
} else {
ele.innerHTML = JSON.parse(evt.data).message[JSON.parse(evt.data).message.length - 1]
if (user.name == JSON.parse(evt.data).name) {
box.style.justifyContent = 'flex-end'
box.appendChild(ele)
box.appendChild(avatar)
} else {
box.appendChild(avatar)
box.appendChild(ele)
}
}
document.body.appendChild(box)
}
webSocket.onclose = function (evt) {
console.log("connection closed")
}
</script>
最简单的基本实现就是如此,完整的聊天室需要考虑的细节更多,暂时就不一一实现
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!