Socket.io 是什么,怎样利用,与 WebSocket 的关系?
先容
上篇我们讲到了 WebSocket 的利用,不太了解的小伙伴,建议先到我上篇文章了解下再来学习。
Socket.io是一个创建在 WebSocket 协议之上的库,他提供了低耽误、双向通讯、基于事件(可以自定义双方约定好的事件)的功能,保证了利用中的稳定性和兼容性,比如用户利用的浏览器版本不支持,会利用 HTTP长轮询 实现:断线自动重连的功能。
与 WebSocket 区别
- Socket.io 固然创建在 WebSocket 协议之上,但不是 WebSocket 的实现。
- 现在仍有些许浏览器无法创建WebSocket连接,利用 Socket.io 可以做兼容性处理,转为 HTTP长轮询。
- 服务器和客户端之间的WebSocket连接大概会中断,双方都不知道连接的中断状态。Socket.io 自带一个心跳机制,它可以定期检查连接的状态,WebSocket 需要手动实现。
- 固然 Socket.io 确实是在客户端支持的情况下利用 WebSocket 举行传输,但是它为每个数据包添加了额外的 元数据。这就是 WebSocket 客户端无法成功连接到 Socket.io 服务端,Socket.io 客户端也无法连接到平凡的WebSocket服务器的缘故起因。以是双方要同时规定好利用 websocket 照旧 Socket.io,不能混用。
- Socket.io 提供了支持派发事件和监听时间的便捷功能,以下是官网案例:
- socket.emit("hello", "world", (response) => {
- console.log(response); // "got it"
- });
- socket.on("hello", (arg, callback) => {
- console.log(arg); // "world"
- callback("got it");
- });
复制代码 上面代码中的"hello"就是双方约定好的事件,寻常项目开发中一般会在前面加上 $,表示自定义事件。
- // socket.io
- io.on("connection", (socket) => {
- socket.broadcast.emit("hello", "world");
- });
- // 原生 websocket
- socket.on('message', (message) => {
- ws.clients.forEach((client) => {
- client.send({
- type: "hello",
- message
- });
- })
- })
复制代码 利用 Socket.io 实现一个浅易聊天室
- 我这里前端利用 vue3+TS,后端 node(这是肯定的,只支持node)
- 先看成品展示,简朴做了一下,样式请不要在乎。。。
- 以下是代码部门
- 前端
- <template>
- <div class="container">
- <div class="users-area">
- <!-- 待开发,感兴趣自己可以试着做做 -->
- <input type="text" placeholder="搜索">
- <ul class="users-list">
- <li v-for="u in users" :key="u">{{ u }}</li>
- </ul>
- </div>
- <div class="msg-area">
- <div class="message-area">
- <div class="item" :class="{ self: self === item.name }" v-for="(item, ind) in msgList" :key="ind">
- <span class="name">{{ item.name }}</span>
- <p class="message">{{ item.message }}</p>
- </div>
- </div>
- <div class="input-area">
- <textarea v-model="message" @keydown.enter="sendMsg"></textarea>
- </div>
- </div>
- </div>
- </template>
复制代码
- <script setup lang="ts">
- import { defineProps, watch, ref, defineEmits } from 'vue';
- const message = ref('');
- const emits = defineEmits(['chat'])
- type Props = {
- users?: any[];
- msgList?: { name: string, message: string}[];
- self: string
- }
- const props = withDefaults(defineProps<Props>(), {
- users: () => [],
- msgList: () => []
- })
- const sendMsg = () => {
- const val = message.value.trim();
- if (val) {
- message.value = '';
- emits('chat', { name: props.self, message: val });
- }
- }
- </script>
复制代码
- <style scoped>
- .container {
- display: flex;
- width: 550px;
- height: 500px;
- border-radius: 8px;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
- background-color: rgb(235, 235, 235);
- overflow: hidden;
- }
- .users-area {
- width: 150px;
- border-right: 1px solid #ccc;
- line-height: 30px;
- overflow: auto;
- flex: 0 0 auto;
- }
- .users-area input {
- margin-top: 10px;
- width: 80%;
- border: none
- }
- .users-area input:focus {
- outline: 1px solid #aaa
- }
- .users-area p {
- text-align: center;
- border-bottom: 1px solid #ccc;
- }
- .users-area .users-list {
- padding: 0;
- margin: 10px 0;
- list-style: none;
- border-top: 1px solid #ccc;
- }
- .users-list li {
- padding: 0 10px;
- margin: 10px 0;
- font-size: 12px;
- border-bottom: 1px solid #ccc;
- background: rgb(220, 220, 220);
- }
- .msg-area {
- display: flex;
- flex-direction: column;
- flex: 1;
- background-color: rgb(245, 245, 245);
- }
- .message-area {
- height: 75%;
- padding: 1em;
- font-size: 14px;
- line-height: 1.3;
- overflow-y: scroll;
- }
- .item {
- float: left;
- max-width: 70%;
- clear: both;
- margin-bottom: 1em;
- }
- .name {
- font-size: 12px;
- color: #333;
- }
- .message {
- border-radius: 6px;
- padding: 10px;
- margin: 4px 0;
- background-color: #fff
- }
- .item.self {
- float: right;
- }
- .self .message {
- background-color: rgb(137, 217, 97);
- }
- .self .name {
- text-align: right;
- }
- .input-area {
- flex: 1;
- border-top: 1px solid #ccc;
- }
- .input-area textarea {
- width: 100%;
- height: 100%;
- padding: 10px 20px;
- border: none;
- outline: none;
- }
- </style>
复制代码
- <template>
- <WeChat :self="self" :msgList="msgList" :users="users" @chat="handleChat" />
- </template>
-
- <script setup lang='ts'>
- import WeChat from '@/components/WeChat.vue';
- import { io, Socket } from 'socket.io-client';
- import { ref, onMounted, onUnmounted } from 'vue';
- interface IChatContent {
- name: string;
- message: string
- }
- const msgList = ref<IChatContent[]>([]);
- const users = ref<string[]>([]);
- const self = ref('');
- const socket = ref<Socket | null>(null);
- onMounted(() => {
- socket.value = io('http://localhost:3000');
- // 接受消息
- socket.value.on('$messages', (data: IChatContent) => {
- msgList.value.push(data);
- });
- // 监听加入聊天室的用户
- socket.value.on('$users', (data: string[]) => {
- users.value = data;
- });
- // 监听其他人发送的消息
- socket.value.on('$msgList', (data: IChatContent[]) => {
- msgList.value = data;
- });
- })
- const handleChat = (data: IChatContent) => {
- msgList.value.push(data);
- // 将当前聊天内容发送给服务器,通知其他人
- (socket.value as Socket).emit('$messages', data.message);
- }
- /**
- * 组件卸载时断开连接
- */
- onUnmounted(() => {
- (socket.value as Socket).disconnect();
- })
- </script>
复制代码
- import { Server } from "socket.io";
- const io = new Server({
- path: '/',
- cors: '*'
- });
- const usersList = []; // 用户集合
- const chatContentList = []; // 消息体集合
- let ind = 0; // 记录当前是第几位成员(做简单区分)
- io.on("connection", (socket) => {
- const userName = '成员' + ++ind;
- usersList.push(userName);
- // 加入新成员并告知客户端(这里不能广播,因为广播不包括自己)
- socket.emit('$users', usersList);
- socket.on('$messages', (message) => {
- const content = {
- name: userName,
- message
- }
- chatContentList.push(content);
- // 给所有用户发送当前用户发来的消息
- socket.broadcast.emit('$messages', content);
- })
- // 监听到连接关闭
- socket.on('disconnect', () => {
- // 清除用户
- usersList.splice(usersList.indexOf(userName), 1);
- // 广播通知所有用户
- socket.broadcast.emit('$users', usersList);
- });
- });
- io.listen(3000);
复制代码
- 更多细节与功能请参考官网:https://socket.io/docs/v4/tutorial/introduction
- 欢迎各位小伙伴指出意见,觉得不错的话不要忘记留下个赞哦,你的鼓励是我更新的动力,谢谢。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |