阿里云部署,基于React、C/C++,使用TCP/HTTP协议的多人聊天室Web应用

10 篇文章 0 订阅
2 篇文章 0 订阅

😃😃😃 本人能力有限,欢迎大佬指正改进~
现在聊天室后台经常挂掉,就没再打开过了😅😅
今后会加以改进,重新上线!🤠

1. 前言

最近和后端同学I’M 渣渣一起完成了一个 Demo 级的多人聊天室应用,实现了聊天室的基本功能。

采用前后端分离方案,我负责前端代码的编写,I’M 渣渣实现了后端的接口。

前后端都部署到了自己的阿里云服务器上。

预览地址:多人聊天室

源码仓库:[前端][后端]


2. 应用简介

1. 主要功能

  1. 用户注册
  2. 用户登录
  3. 发送、接收消息
  4. 退出功能

2. 主要用到的技术

前端:

  1. React 脚手架Create-React-App
  2. 状态管理redux + react-redux
  3. 前端路由 React-Router、路由鉴权
  4. 少量使用 AntD 组件库 (Icon 图标、Notification 通知提醒框、Message 全局提示)

这里仅记录了前端的相关技术,后端基于TCP/HTTP协议,采用 C/C++实现,详情请查看基于阿里云用C/C++做了一个http协议的web聊天室的服务器——《干饭聊天室》

3. 主要功能实现

1. 路由鉴权

将用户的登录状态放入redux,默认为false未登录。

App组件挂载时,判断用户登录状态,若已经登录,则直接跳转到聊天室页面;若未登录,则跳转到注册/登录页面,让用户登录。

<Switch>
    {this.props.loginState ? (
        <Fragment>
            <Route path="/room" component={Room} />
            <Redirect to="/room" />
        </Fragment>
    ) : (
        <Fragment>
            <Route path="/welcome" component={Welcome} />
            <Redirect to="/welcome" />
        </Fragment>
    )}
</Switch>

2. 用户注册

需要验证用户填写的用户名、密码是否符合规范,若不符合规范给出提示并直接return,若符合规范才发送注册请求给服务器。

// 点击按钮,登录
register = () => {
    // 数字字母组合,字母开头
    const unameReg = /^[a-zA-Z][a-zA-Z0-9]{2,9}$/;
    const uname = this.uname.value;
    const pwd = this.pwd.value;
    const pwdAgian = this.pwdAgian.value;
    // 判断用户名是否符合规则
    if (!unameReg.test(uname)) {
        this.openUnameError();
        return;
    }
    // 判断密码长度
    if (!(pwd.length >= 6 && pwd.length <= 16)) {
        this.openPwdError();
        return;
    }
    // 判断两次输入的密码是否一致
    if (pwd !== pwdAgian) {
        this.openPwdUnEqual();
        return;
    }
    // 调用接口,发送注册请求
    const url = `${constUrl}/register`;
    axios({
        method: 'get',
        url,
        params: {
            name: uname,
            pwd,
        },
    })
        .then(res => {
            // 注册成功
            if (res.data.register === 0) {
                this.openRegisterSuccess();
                this.uname.value = '';
                this.pwd.value = '';
                this.pwdAgian.value = '';
                // 跳转到登录页
                this.props.history.replace(`/welcome/login`);
            } else {
                // 注册失败,打开相应的提示框
                switch (res.data.error) {
                    case 0: {
                        this.openUnameReuse();
                        return;
                    }
                    default: {
                        this.openOtherError();
                        return;
                    }
                }
            }
        })
        .catch(err => console.error(err));
};

3. 用户登录

登录功能没什么好说的,收集参数并发送请求就可以了,若登录成功,则给出提示,并更改redux中的登录状态为true,页面自动会跳转到聊天室页面。若登陆失败,则根据服务器返回的数据,给出相应提示。

login = async () => {
    const url = `${constUrl}/login`;
    const name = this.inputUname.value;
    const pwd = this.inputPwd.value;
    axios({
        method: 'get',
        url,
        params: {
            name,
            pwd,
        },
    })
        .then(res => {
            if (res.data.login === 0) {
                this.props.login(name);
                this.openLoginSuccess();
                return;
            }
            switch (res.data.error) {
                case 0: {
                    this.openUnameNotFound();
                    this.props.logout();
                    return;
                }
                case 1: {
                    this.openPwdError();
                    this.props.logout();
                    return;
                }
                case 2: {
                    this.openOtherError();
                    this.props.logout();
                    return;
                }
                default:
                    return;
            }
        })
        .catch(err => console.error(err));

4. 接收消息

接受消息功能,同样也是向服务器发送请求,获得所需消息,并展示在页面上。

这里需要将展示聊天记录容器的滚动条自动调整到底部,详情见JavaScript 实现容器滚动条默认出现在底部位置

由于发送一次接收消息的请求,只能得到一次消息,所以我在componentDidMount()生命周期函数中,开启了一个定时器,每隔 1 秒就发送一次请求,获得所有消息,展示到页面上。由于 React 的diff算法,即使没有新的消息,频繁地发送请求,也不会有浪费太多性能。记得在componentWillUnmount()中,清除定时器。

componentDidMount() {
    this.getMsg();
    this.msgUpdate = setInterval(() => {
        this.getMsg();
    }, 1000);
}
componentWillUnmount() {
    // 清除定时器
    clearInterval(this.msgUpdate);
}
// 获取所需消息
getMsg = () => {
    const url = `${constUrl}/information`;
    const name = this.props.name;
    axios({
        method: 'get',
        url,
        params: { name },
        // responseType: 'blob',
    })
        .then(res => {
            console.log(res);
            // 获取人数
            const userCount = res.data.userCount;
            this.setState({ userCount });
            // 获取新数据
            const newMsg = res.data.msg;
            // 获取原数据
            const oldMsg = this.state.msg;
            if (res.data.information === 0) {
                this.setState({ msg: [...oldMsg, ...newMsg] }, () => {
                    // 滚动条自动到底部
                    this.messageBox.scrollTop = this.messageBox.scrollHeight;
                });
            }
        })
        .catch(err => console.error(err));
};

5. 发送消息

发送请求之前,先判断输入框是否为空。不为空,再进行下一步,发送请求。

成功发送消息后,调用一次接收消息函数,获得所有消息,即可将刚刚发送的消息立即展示到页面。

   // 发送消息
   sendMsg = () => {
    const msg = this.editMsg.value;
    const name = this.props.name;
    if (msg === '') {
        message.warning('请输入消息!');
        return;
    }
    const url = `${constUrl}/information`;
    axios({
        method: 'post',
        url,
        params: {
            msg,
            name,
            time: new Date().getTime(),
            id: nanoid(),
        },
    })
        .then(res => {
            // console.log(res);
            if (res.data.msg === 0) {
                this.editMsg.value = '';
                message.success('发送成功!');
                // 调用获取所有消息函数
                this.getMsg();
            }
        })
        .catch(err => console.error(err));

6. 退出功能

退出时,发送请求给服务器,告诉服务器有用户退出了、哪个用户退出了,主要用于展示当前在线人数。

redux中的登录状态改为false,页面自动跳转到注册/登录页面。

logout = () => {
    const url = `${constUrl}/logout`;
    const name = this.props.name;
    axios({
        method: 'get',
        url,
        params: {
            name,
        },
    });
    this.openLogout();
    this.props.logout();
};

4. 前端部署

前端应用经过React脚手架打包后,部署到了阿里云服务器上。

采用nginx服务器配置,配置如下:

server{
        listen    80;
        root /home/www/chatRoom;
        server_name 47.110.144.145;
        error_page 404 /index.html;

        location /{}
}

5. Todo

由于本人能力有限,本 Demo 还有一些BUG没有解决:

  1. 当前在数人数显示模块没有正常工作,若用户不点击退出按钮,直接关闭浏览器页面,没有监听到用户的退出动作。
  2. 接收到的消息中,空格?=#等字符会显示其编码,无法正常显示。

将来可能添加的功能:

  1. 采用token验证用户身份

  2. 自定义背景图片切换

  3. 支持黑暗模式

  4. 适配移动端

  5. 支持上传头像

  6. 支持发送图片


📘📘欢迎在我的博客上访问:
https://lzxjack.top/

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
基于React和Ant Design,我们可以使用一些库来实现在纯前端中导入Excel文件。 首先,我们可以使用`react-excel-to-json`库将Excel文件转换为JSON格式。通过这个库,我们可以将Excel文件转换为JSON对象,方便我们在前端进行处理和展示。 其次,Ant Design的Upload组件可以帮助我们实现文件上传功能。我们可以使用`beforeUpload`属性来限制上传文件的类型为Excel文件。一旦用户上传了Excel文件,我们就可以调用`react-excel-to-json`来实现文件的解析,将Excel文件转换为JSON数据。 最后,我们可以通过自定义组件来展示解析后的数据。我们可以使用Table组件来展示JSON数据,将每一行数据显示在表格中。 下面是一个示例代码,演示了如何在基于React和Ant Design的纯前端应用中实现导入Excel文件功能: ```jsx import React from 'react'; import { Upload, Button, Table } from 'antd'; import { ExcelRenderer } from 'react-excel-to-json'; class ExcelImporter extends React.Component { state = { excelData: [], }; handleImportExcel = (file) => { ExcelRenderer(file, (err, res) => { if (err) { console.log(err); } else { this.setState({ excelData: res.rows }); } }); }; render() { const { excelData } = this.state; const columns = excelData.length > 0 ? Object.keys(excelData[0]) : []; return ( <div> <Upload beforeUpload={this.handleImportExcel}> <Button>导入Excel文件</Button> </Upload> {excelData.length > 0 && ( <Table dataSource={excelData} columns={columns.map((column) => ({ dataIndex: column, title: column }))} /> )} </div> ); } } export default ExcelImporter; ``` 在这个示例中,我们通过`Upload`组件来实现文件的上传,通过`beforeUpload`属性限制了只能上传Excel文件。在`handleImportExcel`方法中,我们调用了`ExcelRenderer`来将Excel文件解析为JSON数据,并将数据保存在组件的状态中。 在页面上,我们使用了`Table`组件来展示解析后的JSON数据,通过`dataSource`属性传入数据,通过`columns`属性定义表格的列。 这样,用户在选择并上传Excel文件后,我们就可以在前端解析并展示Excel中的数据了。这种方式适用于只需要在前端进行Excel数据处理和展示的场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

火星飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值