前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >丑low的聊天室

丑low的聊天室

作者头像
一粒小麦
发布2019-07-18 18:54:35
6990
发布2019-07-18 18:54:35
举报
文章被收录于专栏:一Li小麦一Li小麦

笔者第一次上网,学校网络室给定制的首页是一个红泥巴的聊天室。这回去看了下,卧槽还没倒闭:

果然是经得起时间考验的项目了。

socket实现——一个即时终端聊天室

net模块提供一个异步api能够创建基于流的tcp服务器,客户端和服务端建立连接之后,服务器可以获得一个双工socket对象,服务器可以保存socket对象列表,在接受某客户端消息时,推送给其他客户端。

代码语言:javascript
复制
// socket.js
const net=require('net');
const chatServer=net.createServer();
const clientList=[];

chatServer.on('connection',client=>{
    client.write('Hi\n');
    clientList.push(client);
    // 当接收到数据时:
    client.on('data',data=>{
        console.log(`receive:${data.toString()}`);
        clientList.forEach(v=>{
            v.write(data);
        })
    })
});
chatServer.listen(9000);

如何测试呢?这里用到telnet:

telnet本来是mac os 10.13之前的内置服务,在高级版本中,需要本地安装一下:

代码语言:javascript
复制
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install telnet

安装完成之后:

代码语言:javascript
复制
telnet localhost 9000

打印出'hi'

假设再建立一个客户端:同样也能收到消息。

网络聊天室

http的一个重要弱点在于,只能拉取,不能主动推送。所以后端扯皮时会说:'"你不穿东西给我,我就没东西给你。"这个时候只好做轮询(苦了前端)。

从项目角度说,HTTP协议是非持久化的,单向的网络协议,在建立连接后只允许浏览器向服务器发出请求后,服务器才能返回相应的数据。当需要即时通讯时,通过轮询在特定的时间间隔(如1秒),由浏览器向服务器发送Request请求,然后将最新的数据返回给浏览器。这样的方法最明显的缺点就是需要不断的发送请求,而且通常HTTP request的Header是非常长的,为了传输一个很小的数据 需要付出巨大的代价,是很不合算的,占用了很多的宽带

但如果有了socket.io,事情就好办多了。

Socket.io是一个WebSocket库,包括了客户端的js和服务器端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5

代码语言:javascript
复制
npm i socket.io -S

在后端基本上不需要做什么处理:

代码语言:javascript
复制
// 服务端:chat-socketio.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function (req, res) {
    res.sendFile(__dirname + '/index.html');
});

io.on('connection', function (socket) {
    console.log('a user connected');
    io.emit('chat message', {
        type:'notice',
        time:new Date().toLocaleString(),
        name:'新用户',
        msg:'加入了群聊'
    });


    //响应某用户发送消息
    socket.on('chat message', function (msg) {
        console.log('chat message:' + msg);
        // 广播给所有人
        io.emit('chat message', msg);
        // 广播给除了发送者外所有人
        // socket.broadcast.emit('chat message', msg)
    });
    socket.on('disconnect', function () {
        io.emit('chat message', {
            msg:'用户退出了群聊',
            type:'notice',
            name:'有用户',
            time:new Date().toLocaleString(),
        });
        console.log('user disconnected');
    });
});


http.listen(3000, function () {
    console.log('listening on *:3000');
});

前端:

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style type="text/css">
            /* blabla */
    </style>
</head>

<body>
    <div id="root">
        <!-- <input type="file" name="file" id="upload"> -->
        <div id="dialog">

        </div>

        <div id="control">
            <input id="username" type="text">
            <textarea id="msg" cols="30" rows="10"></textarea>
            <button id="send">发送</button>
        </div>
    </div>
    <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
    <script>
        var dialog = document.querySelector('#dialog');
        var send = document.querySelector('#send');
        var msg = document.querySelector('#msg');
        var socket = io();
        send.addEventListener('click', (e) => {
            socket.emit("chat message", {
                name:document.querySelector('#username').value,
                msg:msg.value,
                time:new Date().toLocaleString(),
                type:'normal'
            });
        })
        socket.on("chat message", function (msg) {
            let html=``;

            switch (msg.type) {
                case 'notice':
                    html=`<div class="notice">
                    ${msg.name} ${msg.msg} <small>${msg.time}</small>
                </div>`;
                    break;

                default:
                    html=`<div class="msg-wrap">
                    <div class="name">${msg.name} <small>${msg.time}</small></div>
                    <div class=""msg">${msg.msg}</div>
                </div>`
                    break;
            }
            dialog.innerHTML+=html;
            dialog.scrollTop = dialog.scrollHeight;
        });

    </script>
</body>

</html>

那么就实现了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一Li小麦 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 网络聊天室
相关产品与服务
即时通信 IM
即时通信 IM(Instant Messaging)基于腾讯二十余年的 IM 技术积累,支持Android、iOS、Mac、Windows、Web、H5、小程序平台且跨终端互通,低代码 UI 组件助您30分钟集成单聊、群聊、关系链、消息漫游、群组管理、资料管理、直播弹幕和内容审核等能力。适用于直播互动、电商带货、客服咨询、社交沟通、在线课程、企业办公、互动游戏、医疗健康等场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档