websocket协议—socket.io设计一个简易聊天室 (二)

路雅懿
2023-12-01

介绍了原生websocket的使用,接着学习使用socket.io:

socket.io 是基于 WebSocket 的 C-S 实时通信库,底层是 engine.io,这个库实现了跨平台的双向通信。
engine.io 使用了 WebSocket 和 XMLHttprequest(或JSONP) 封装了一套自己的 Socket 协议(暂时叫 EIO Socket),在低版本浏览器里面使用长轮询替代 WebSocket。一个完整的 EIO Socket 包括多个 XHR 和 WebSocket 连接.

常用api:

socket.emit

数据传输对象为当前socket对应的client,其他各个client socket互相不影响;

socket.broadcast.emit

数据传输对象为所有client,排除当前socket对应的client;

io.sockets.emit

数据传输对象为所有client,包括触发当前事件的client;


使用:

1.安装express,聊天室需要局域网的呀,局域网需要启动http服务呀,所以安装express;


2.安装socket.io,cnpm i --save socket.io   装好后它分为前端、后端两部分,前端页面引入:<script src="/socket.io/socket.io.js"></script>(在文件中看不到,等连接服务的时候就会出现),会自动生成一个文件夹名字就叫socket.io,以及文件夹内生成socket.io.js文件


3.创建mainjs文件,开始撸:

直接贴出写好的代码了:

mainjs:

var express = require("express");
var app = express();
//因为socket.io依赖原生http服务,所以要引入原生http模块,并且调用它的Server()方法将app传入,这样原生的http就拥有了express的方法
var http = require("http").Server(app);
var socket = require("socket.io")(http);//传入http执行socket函数,这样socket就跟http具有同一个端口了
http.listen(9999);

app.use(express.static("./html"));//设置静态资源路径

// 创建socket监听服务:
socket.on("connection", function(ws){
	ws.on("diyLogin", function(val){//定义一个完全自定义事件,用来获取前端发来的登录的用户名
		var address = ws.handshake.address;
		console.log(address);
		var u =  checkUser(val);
		if(u.err){
            ws.emit("exist", u);
        }else{
        	socket.sockets.emit("allLogin", u);//执行前端事件,发送范围为每一个在线的客户端
        }
	});

	ws.on("sendMsg", function(msgObj){
		socket.sockets.emit("accept", msgObj);//把接收到的某个用户消息发送到所有客户端
	})
	
})

var arr = [];
function checkUser(u){//检测用户名是否已存在
	if(arr.length === 0){
		arr.push(u);
		return u;
	};
	for(var i = 0; i < arr.length; i++){
		if(arr[i] === u){
			return {
				err: "用户名已存在",
				users: arr
			}
		}
	}
	arr.push(u);
	return u;
}

html:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
	<style>
    i{
        font-style: normal;
    }
       .chatList{
       	  height: 200px;
       	  border: 1px dashed green;
       	  overflow-y: auto;
       }
       .myself{
       	  text-align: right;
       	  color: red;
       }
       i.lin{
        font-weight: bold;
        color: #ffcc01;
        font-size: 16px;
       }
       i.other{
        color: green;
       }
       p.me{
        text-align: right;
        color: orange;
       }
	</style>
</head>
<body>
	<div class="container">
		<div class="loginBox">
			  <input type="text" class="form-control" id="username">
		      <button class="btn" id="sure">登录</button>
		</div>
        <div class="chatBox hidden">
        	<div class="chatList">
        		
        	</div>
            <textarea class="form-control" id="msg" cols="30" rows="5"></textarea>
            <button class="btn" id="send">发送</button>
            <div class="alert alert-success hidden" role="alert"></div>
        </div>
	</div>
</body>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
	//链接socket
    var ws = io.connect("ws://localhost:9999");
    var user;
    $("#sure").click(function(){
        var name = $("#username").val();
        if(!name){
            alert("好歹起个名呀,eg:李易峰");
        }else{
            //通知后台有人登陆了,socket.io都是基于事件的,要做的操作都是触发自定义事件的方式
            ws.emit("diyLogin", name);//执行自定义事件传入用户名
            user = name;//把当前用户名称保存到全局变量
        }
   })
    //获取后端返回的用户是否存在的查询结果
    ws.on("exist", function(re){
        if(re.err){
            alert(re.err);
            console.log("已经登陆的用户:\n", re.users)
            return;
        }
    })

    //接收后端返回的全局的登录者的名字的事件
    ws.on("allLogin", function(name){
        var _alert = name === "赵治林" ? "欢迎 男爵 <i class='lin'>"+name+"</i> 骑着火麒麟来到了本直播间!" : "<i class='other'>"+name+" </i>进入直播间";
         $(".alert").html(_alert).removeClass("hidden").show();
         $(".loginBox").hide();//登陆后隐藏登录盒子
         $(".chatBox").removeClass("hidden");//显示出聊天界面
         setTimeout(function(){
            $(".alert").fadeOut(function(){
                $(this).addClass("hidden");
            });
         }, 1500)
    })
    //发送聊天消息
    $("#send").click(function(){
        var msg = $("#msg").val();
        if(!msg){
            alert("空消息也要钱哦!");
        }else{
            ws.emit("sendMsg", {msg, user});//执行事件把内容和发送者发送给后台,让后台返回给所有客户端
            $("#msg").val("");
        }
    })
    //接收聊天消息
    ws.on("accept", function(o){
        var p = $(`<p>${o.user}: ${o.msg}</p>`)
        if(o.user === user){
            p.addClass("me");
        }
        $(".chatList").append(p).scrollTop($(".chatList")[0].scrollHeight);
    })
</script>
</html>
个人理解:

socket.io实现了一对多的B-S双向通信,是基于事件驱动的,相当于后台自定义一个事件,前端触发,前端自定义一个事件,后台触发,同时可以选择socket.io提供的方法指定数据发送的范围,比如发给哪一个客户端;





 类似资料: