fastadmin实现站内通知功能

news2024/11/23 16:58:46

实现效果如下
在这里插入图片描述
在这里插入图片描述
application/admin/view/common/header.html

<style>
    #notificationMenu {
        display: none;
        position: absolute;
        top: 40px;
        right: 0;
        background: #fff;
        border-radius: 6px;
        padding: 10px 0;
        width: 300px;
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
        z-index: 1000;
    }

    #notificationItem {
        display: block !important;
    }

    #notificationIcon {
        display: inline-block;
    }

    #notificationMenu .menu li {
        padding: 12px 15px;
        border-bottom: 1px solid #f0f0f0;
        transition: background-color 0.3s ease;
        cursor: pointer;
    }

    #notificationMenu .menu li:hover {
        background-color: #f7f7f7;
    }

    #notificationMenu .menu {
        max-height: 250px;
        overflow-y: auto;
    }

    .badge {
        position: relative;
        top: -10px;
        right: -10px;
    }
</style>
<!-- Logo -->
<a href="javascript:;" class="logo">
    <!-- 迷你模式下Logo的大小为50X50 -->
    <span class="logo-mini">{$site.name|mb_substr=0,4,'utf-8'|mb_strtoupper='utf-8'|htmlentities}</span>
    <!-- 普通模式下Logo -->
    <span class="logo-lg">{$site.name|htmlentities}</span>
</a>

<!-- 顶部通栏样式 -->
<nav class="navbar navbar-static-top">

    <!--第一级菜单-->
    <div id="firstnav">
        <!-- 边栏切换按钮-->
        <a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
            <span class="sr-only">{:__('Toggle navigation')}</span>
        </a>

        <!--如果不想在顶部显示角标,则给ul加上disable-top-badge类即可-->
        <ul class="nav nav-tabs nav-addtabs disable-top-badge hidden-xs" role="tablist">
            {$navlist}
        </ul>

        <div class="navbar-custom-menu">
            <ul class="nav navbar-nav">

                <!-- 通知图标 -->
                <li id="notificationItem" class="dropdown notifications-menu" style="display: block;">
                    <a href="#" id="notificationIcon">
                        <i class="fa fa-bell"></i>
                        <span id="notificationBadge" class="badge badge-danger">{$notice|default=0}</span>
                    </a>
                    <ul id="notificationMenu" class="dropdown-menu">
                        <li style="padding: 10px; display: flex; justify-content: space-between; align-items: center;">
                            <a href="javascript:void(0);" id="doNotDisturbButton" style="display: flex; align-items: center;">
                                <i class="fa fa-bell" id="doNotDisturbIcon" style="margin-right: 5px;"></i> 免打扰
                            </a>
                            <a href="javascript:void(0);" id="markAllReadButton">
                                <i class="fa fa-check-circle"></i> 一键已读
                            </a>
                        </li>
                        <li>
                            <ul id="notificationList" class="menu"></ul>
                        </li>
                    </ul>
                </li>


                <!-- 多语言列表 -->
                {if $Think.config.lang_switch_on}
                <li class="hidden-xs">
                    <a href="javascript:;" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-language"></i></a>
                    <ul class="dropdown-menu">
                        <li class="{$config['language']=='zh-cn'?'active':''}">
                            <a href="?ref=addtabs&lang=zh-cn">简体中文</a>
                        </li>
                        <li class="{$config['language']=='en'?'active':''}">
                            <a href="?ref=addtabs&lang=en">English</a>
                        </li>
                    </ul>
                </li>
                {/if}

                <!-- 账号信息下拉框 -->
                <li class="dropdown user user-menu">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                        <img src="{$admin.avatar|cdnurl|htmlentities}" class="user-image" alt="">
                        <span class="hidden-xs">{$admin.nickname|htmlentities}</span>
                    </a>
                    <ul class="dropdown-menu">
                        <!-- User image -->
                        <li class="user-header">
                            <img src="{$admin.avatar|cdnurl|htmlentities}" class="img-circle" alt="">

                            <p>
                                {$admin.nickname|htmlentities}
                                <small>{$admin.logintime|date="Y-m-d H:i:s",###}</small>
                            </p>
                        </li>
                        <li class="user-body">
                            <div class="visible-xs">
                                <div class="pull-left">
                                    <a href="__PUBLIC__" target="_blank"><i class="fa fa-home"
                                                                            style="font-size:14px;"></i>
                                        {:__('Home')}</a>
                                </div>
                                <div class="pull-right">
                                    <a href="javascript:;" data-type="all" class="wipecache"><i
                                            class="fa fa-trash fa-fw"></i> {:__('Wipe all cache')}</a>
                                </div>
                            </div>
                        </li>
                        <!-- Menu Footer-->
                        <li class="user-footer">
                            <div class="pull-left">
                                <a href="general/profile" class="btn btn-primary addtabsit"><i class="fa fa-user"></i>
                                    {:__('Profile')}</a>
                            </div>
                            <div class="pull-right">
                                <a href="{:url('index/logout')}" class="btn btn-danger"><i class="fa fa-sign-out"></i>
                                    {:__('Logout')}</a>
                            </div>
                        </li>
                    </ul>
                </li>
                <!-- 控制栏切换按钮 -->
                <li class="hidden-xs">
                    <a href="javascript:;" data-toggle="control-sidebar"><i class="fa fa-gears"></i></a>
                </li>
            </ul>
        </div>
    </div>

    {if $Think.config.fastadmin.multiplenav}
    <!--第二级菜单,只有在multiplenav开启时才显示-->
    <div id="secondnav">
        <ul class="nav nav-tabs nav-addtabs disable-top-badge" role="tablist">
            {if $fixedmenu}
            <li role="presentation" id="tab_{$fixedmenu.id}" class="{:$referermenu?'':'active'}"><a
                    href="#con_{$fixedmenu.id}" node-id="{$fixedmenu.id}" aria-controls="{$fixedmenu.id}" role="tab"
                    data-toggle="tab"><i class="fa fa-dashboard fa-fw"></i> <span>{$fixedmenu.title}</span> <span
                    class="pull-right-container"> </span></a></li>
            {/if}
            {if $referermenu}
            <li role="presentation" id="tab_{$referermenu.id}" class="active"><a href="#con_{$referermenu.id}"
                                                                                 node-id="{$referermenu.id}"
                                                                                 aria-controls="{$referermenu.id}"
                                                                                 role="tab" data-toggle="tab"><i
                    class="fa fa-list fa-fw"></i> <span>{$referermenu.title}</span> <span
                    class="pull-right-container"> </span></a> <i class="close-tab fa fa-remove"></i></li>
            {/if}
        </ul>
    </div>
    {/if}
</nav>

<script>
    function initNotifications() {
        const notificationIcon = document.getElementById("notificationIcon");
        const notificationMenu = document.getElementById("notificationMenu");
        const notificationList = document.getElementById("notificationList");
        const notificationBadge = document.getElementById("notificationBadge");
        const doNotDisturbButton = document.getElementById("doNotDisturbButton");
        const doNotDisturbIcon = document.getElementById("doNotDisturbIcon");

        let notifications = []; // 初始通知列表
        let doNotDisturb = localStorage.getItem("doNotDisturb") === "true";

        // 更新免打扰图标状态
        function updateDoNotDisturbIcon() {
            doNotDisturbIcon.className = doNotDisturb ? "fa fa-bell-slash" : "fa fa-bell";
            // 同步主通知图标样式
            const notificationIconBell = document.querySelector("#notificationIcon i");
            if (notificationIconBell) {
                notificationIconBell.className = doNotDisturb ? "fa fa-bell-slash" : "fa fa-bell";
            }
        }

        // 切换免打扰模式
        doNotDisturbButton.addEventListener("click", () => {
            doNotDisturb = !doNotDisturb;
            localStorage.setItem("doNotDisturb", doNotDisturb);
            updateDoNotDisturbIcon();
            // 同步主通知图标样式
            const notificationIconBell = document.querySelector("#notificationIcon i");
            if (notificationIconBell) {
                notificationIconBell.className = doNotDisturb ? "fa fa-bell-slash" : "fa fa-bell";
            }
            Toastr.info(doNotDisturb ? "已开启免打扰模式" : "已关闭免打扰模式");
        });

        // 初始化免打扰图标
        updateDoNotDisturbIcon();

        // 一键已读功能
        document.getElementById("markAllReadButton").addEventListener("click", markAllAsRead);
        //全部已读
        function markAllAsRead() {
            $.ajax({
                url: "notice/markAllAsRead",
                method: "POST",
                success: function (data) {
                    if (data.code === 1) {
                        notifications.forEach((notif) => (notif.read = 2)); // 更新本地状态
                        updateNotifications();
                        Toastr.success("全部已读");
                    } else {
                        Toastr.error(data.msg || "一键已读失败");
                    }
                },
                error: function () {
                    Toastr.error("网络错误,无法一键已读");
                },
            });
        }

        // 获取通知列表
        function fetchNotifications() {
            $.ajax({
                url: "notice/noticelist",
                method: "GET",
                success: function (response) {
                    if (response.code === 1 && Array.isArray(response.data)) {
                        notifications = response.data.map((item) => ({
                            id: item.id,
                            text: item.title,
                            read: item.read,
                        }));
                        updateNotifications();
                    } else {
                        Toastr.error(response.msg || "获取通知失败");
                    }
                },
                error: function () {
                    Toastr.error("网络错误,无法获取通知");
                },
            });
        }

        // 更新通知列表和未读数
        function updateNotifications() {
            const fragment = document.createDocumentFragment();
            let unreadCount = 0;

            notificationList.innerHTML = "";
            notifications.forEach((notif) => {
                const li = document.createElement("li");
                li.textContent = notif.text;
                li.style.opacity = notif.read > 1 ? "0.5" : "1";

                if (notif.read == 1) unreadCount++;

                li.addEventListener("click", () => {
                    notif.read = 2
                    updateNotifications();
                    markAsRead(notif.id); // 标记为已读
                });

                fragment.appendChild(li);
            });

            notificationList.appendChild(fragment);
            notificationBadge.textContent = unreadCount;
        }

        // 单个标记为已读
        function markAsRead(id) {
            $.ajax({
                url: "notice/markAsRead",
                method: "GET",
                data: { id: id },
                success: function (data) {
                    if (data.code !== 1) {
                        console.error(data.msg || "标记已读失败");
                    }
                },
                error: function () {
                    Toastr.error("网络错误,无法标记为已读");
                },
            });
        }

        // 点击通知图标时
        notificationIcon.addEventListener("click", () => {
            notificationMenu.classList.toggle("show");
            if (notificationMenu.classList.contains("show")) {
                fetchNotifications();
            }
        });

        // 点击外部关闭菜单
        document.addEventListener("click", (e) => {
            if (!notificationMenu.contains(e.target) && e.target !== notificationIcon) {
                notificationMenu.classList.remove("show");
            }
        });
    }

    // 等待 DOM 加载完成后运行
    document.addEventListener("DOMContentLoaded", initNotifications);
</script>

public/assets/js/backend/index.js

				var connectWebSocket = function () {
                var ws = new WebSocket(Config.socket_url);

                ws.onopen = function () {
                    console.log("WebSocket连接已建立");
                };

                ws.onmessage = function (event) {
                    var message = JSON.parse(event.data);

                    //处理消息通知
                    if (message && message.type === "ping") {
                        // console.log(message)
                        let doNotDisturb = localStorage.getItem("doNotDisturb");
                        if (!doNotDisturb||doNotDisturb === 'false') {
                            //判断是否设置免打扰模式
                            Toastr.info(message.content || "您有一条新消息");
                        }
                        console.log(doNotDisturb)

                        // 更新角标-未读数加 1
                        const badgeElement = document.getElementById("notificationBadge");
                        badgeElement.textContent = parseInt(badgeElement.textContent || 0) + 1;
                    }

                    // 处理 "init" 消息类型并发送 AJAX 请求
                    else if (message && message.type === "init") {
                        //Toastr.success(message.content || "Socket 链接成功");

                        // 发送 AJAX 请求到 admin/index/bind_admin 接口,传递 client_id
                        $.ajax({
                            url: 'index/bind_admin',
                            type: 'POST',
                            data: {
                                client_id: message.client_id
                            },
                            dataType: 'json',
                            success: function (response) {
                                if (response.code === 1) {
                                    Toastr.info(response.content || "Socket 绑定成功");
                                } else {
                                    Toastr.error(response.content || "Socket 绑定失败");
                                }
                            },
                            error: function () {
                                Toastr.error("网络错误,绑定失败");
                            }
                        });
                    }
                };

                ws.onclose = function () {
                    console.log("WebSocket连接已关闭,正在重连...");
                    setTimeout(connectWebSocket, 10000);  // 延迟10秒自动重连
                };

                ws.onerror = function () {
                    Toastr.error("socket链接失败");
                };

                return ws;
            };

            // 初始化WebSocket连接
            var ws = connectWebSocket();

application/admin/controller/Notice.php

<?php

namespace app\admin\controller;

use app\common\controller\Backend;

/**
 * 消息通知管理
 *
 * @icon fa fa-circle-o
 */
class Notice extends Backend
{
    
    /**
     * Notice模型对象
     *
     * @var \app\admin\model\Notice
     */
    protected $model = null;
    
    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\Notice;
        $this->view->assign("roleList", $this->model->getRoleList());
        $this->view->assign("readList", $this->model->getReadList());
    }
    
    //消息通知列表
    public function noticelist()
    {
        $notifications = $this->model
            ->where(['role' => 1, 'uid' => $this->auth->id])
            ->order('id desc')
            ->select();
        $this->success('获取成功', '', $notifications);
    }
    
    //标记已读
    public function markAsRead()
    {
        $id = input('id');
        if (!$id) {
            $this->error('参数错误');
        }
        $info = $this->model->where(['id' => $id])->find();
        if (!$info) {
            $this->error('数据读取失败');
        }
        
        $info->save(['read' => 2]);
        $this->success('已标记为已读');
    }
    
    //全部已读
    public function markAllAsRead()
    {
        $uid = $this->auth->id;
        $sql = $this->model->where(['role' => 1, 'uid' => $uid])->update(['read' => 2]);
        if (!$sql){
            $this->error('无数据更新');
        }
        $this->success('已标记为已读');
    }
}

musql表结构如下

CREATE TABLE `fa_notice` (
	`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
	`title` VARCHAR(255) NULL DEFAULT '0' COMMENT '消息标题' COLLATE 'utf8_general_ci',
	`content` TEXT NULL DEFAULT NULL COMMENT '消息内容' COLLATE 'utf8_general_ci',
	`uid` INT(11) NULL DEFAULT '0' COMMENT '收消息方用户id',
	`role` ENUM('1','2') NOT NULL COMMENT '推送:1=向后台推送,2=向用户推送' COLLATE 'utf8_general_ci',
	`read` ENUM('1','2') NULL DEFAULT '1' COMMENT '查看状态:1=未读,2=已读' COLLATE 'utf8_general_ci',
	`createtime` BIGINT(16) NULL DEFAULT NULL,
	`updatetime` BIGINT(16) NULL DEFAULT NULL,
	PRIMARY KEY (`id`) USING BTREE
)
COMMENT='消息通知表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=5
;

在这里插入图片描述
index.php映射

//获取websocket链接
$this->assignconfig('socket_url', Config::get('websocket.url')?Config::get('websocket.url'):'ws://127.0.0.1:8282');

//js中Config.socket_url就可以读取值

config.php

//配置websocket地址
    'websocket' => [
        'url' => 'ws://127.0.0.1:8282',//本地测试
    ],

Backend.php 映射未读消息数量

//渲染消息总数量--判断是否登录
        if ($this->auth->id){
            $notice_num = Db::name('notice')->where(['role'=>1,'read'=>1,'uid'=>$this->auth->id])->count();
            $this->assign('notice', $notice_num);
        }

整体实现效果逻辑
映射页面时,先查询统计消息表未读消息,让角标加载后显示未读消息数量

index.js连接websocket,实现角标未读数值更新,如果有新推送消息,角标数字+1,并弹出新消息提示框(如果设置了免打扰,免打扰的值使用localStorage.setItem存储,判断有没有该值进行是否弹框提醒。免打扰下只更新角标)
在这里插入图片描述

在这里插入图片描述
点击icon访问列表接口,渲染出未读消息,点击消息实现消息更新已读状态。点击一键已读,把当前用户的消息update一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2246135.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

默语博主的推荐:探索技术世界的旅程

这是第一位推荐的博主默语 引言&#xff1a; CSDN中的默语博主是一个值得关注和学习的技术大拿。他的博客内容不仅涵盖了各种热门的技术领域&#xff0c;还能够帮助读者深入了解技术背后的原理和应用。在这篇类博客的内容中&#xff0c;我们将探索默语博主推荐的几篇博客&#…

【漏洞复现】|智互联SRM智联云采系统quickReceiptDetail SQL注入漏洞

漏洞描述 智互联(深圳)科技有限公司SRM智联云采系统针对企业供应链管理难题&#xff0c;及智能化转型升级需求&#xff0c;智联云采依托人工智能、物联网、大数据、云等技术&#xff0c;通过软硬件系统化方案&#xff0c;帮助企业实现供应商关系管理和采购线上化、移动化、智能…

【数据分析】认清、明确

1、什么是数据分析。 - 通过对大量的数据进行科学的分析。 - 得出结论&#xff0c;提出建议&#xff0c;辅助公司企业的决策。2、数据分析分为几步。 - 1.明确目的! - 2.收集数据!自己的数据! 自动化采集的数据! - 3.数据处理! - 4.数据分析!数据分析(业务)数据挖掘(代码算法…

前后端分离,解决vue+axios跨域和proxyTable不生效等问题

看到我这篇文章前可能你以前看过很多类似的文章。至少我是这样的&#xff0c;因为一直没有很好的解决问题。 正文 当我们通过webstorm等IDE开发工具启动项目的时候&#xff0c;通过命令控制台可以观察到启动项目的命令 如下&#xff1a; webpack-dev-server --inline --prog…

WPF中如何让Textbox显示为一条直线

由于Textbox直接使用是一条直线 设置如下代码 可以让Textbox变为直线输入 <Style TargetType"TextBox"x:Key"UsernameTextBoxStyle"><Setter Property"Template"><Setter.Value><ControlTemplate TargetType"{x:Typ…

TSmaster Measurement setup(测量设置)

文章目录 1、Measurement setup功能介绍2、数据流过滤3、Measurement Filter 测量过滤器3.1 插入过滤器3.2 设置过滤数据3.3 过滤条件的失能3.4 窗口缩放 1、Measurement setup功能介绍 Measurement setup 窗体主要包含三个功能&#xff1a; 提供一个面板&#xff0c;用户能够…

[Unity Demo]从零开始制作空洞骑士Hollow Knight第二十集:制作专门渲染HUD的相机HUD Camera和画布HUD Canvas

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、制作HUD Camera以及让两个相机同时渲染屏幕二、制作HUD Canvas 1.制作法力条Soul Orb引入库2.制作生命条Health读入数据3.制作吉欧统计数Geo Counter4.制作…

万字长文解析Golang高性能内存缓存库BigCache

项目地址 BigCache 是一个快速&#xff0c;支持并发访问&#xff0c;自淘汰的内存型缓存&#xff0c;可以在存储大量元素时依然保持高性能。BigCache将元素保存在堆上却避免了GC的开销。 背景介绍 BigCache的作者在项目里遇到了如下的需求&#xff1a; 支持http协议支持 10…

vulfocus在线靶场:骑士cms_cve_2020_35339:latest 速通手册

目录 一、启动环境&#xff0c;访问页面&#xff0c;ip:端口号/index.php?madmin,进入后台管理页面&#xff0c;账号密码都是adminadmin 二、进入之后&#xff0c;根据图片所示&#xff0c;地址后追加一下代码&#xff0c;保存修改 ​三、新开标签页访问&#xff1a;①ip:端…

【数据结构】归并排序 —— 递归及非递归解决归并排序

归并排序 一、归并排序1、归并排序的思想2、归并排序代码实现&#xff08;递归&#xff09;<1> 归并排序的递归区间<2> 归并排序的稳定性<3> 拷贝 3、归并排序代码实现&#xff08;非递归&#xff09;<1> 循环区间溢出问题 二、总结 一、归并排序 1、…

Java技术复习提升 10异常

10 异常 10.1异常介绍及分类 异常捕获 选中后alttabt->选中try-catch 异常就是程序执行中不正常的情况 注意语法和逻辑错误并不是异常 异常分类有两种 error和exception error是错误 虚拟机无法解决的严重问题 exception是其他因为编程错误或者外在因素导致的一般性的问…

transformer.js(三):底层架构及性能优化指南

Transformer.js 是一个轻量级、功能强大的 JavaScript 库&#xff0c;专注于在浏览器中运行 Transformer 模型&#xff0c;为前端开发者提供了高效实现自然语言处理&#xff08;NLP&#xff09;任务的能力。本文将详细解析 Transformer.js 的底层架构&#xff0c;并提供实用的性…

HCIA笔记3--TCP-UDP-交换机工作原理

1. tcp协议 可靠的连接 1.1 报文格式 1.2 三次握手 1.3 四次挥手 为什么TIME_WAIT需要2MSL的等待时间&#xff1f; &#xff08;a&#xff09; 为了实现可靠的关闭 &#xff08;b&#xff09;为了让过期的报文在网络上消失 对于(a), 假设host发给server的last ack丢了。 ser…

[Redis#2] 定义 | 使用场景 | 安装教程 | 快!

目录 1. 定义 In-memory data structures 在内存中存储数据 2. 优点&#xff01;快 Programmability 可编程性 Extensibility 扩展性 Persistence 持久化 Clustering 分布式集群 High availability 高可用性 ⭕快速访问的实现 3. 使用场景 1.Real-time data store …

Dubbo源码解析-服务调用(七)

一、服务调用流程 服务在订阅过程中&#xff0c;把notify 过来的urls 都转成了invoker&#xff0c;不知道大家是否还记得前面的rpc 过程&#xff0c;protocol也是在服务端和消费端各连接子一个invoker&#xff0c;如下图&#xff1a; 这张图主要展示rpc 主流程&#xff0c;消费…

Postman之newman

系列文章目录 1.Postman之安装及汉化基本使用介绍 2.Postman之变量操作 3.Postman之数据提取 4.Postman之pm.test断言操作 5.Postman之newman Postman之newman 1.基础环境node安装1.1.配置环境变量1.2.安装newman和html报告组件 2.newman运行 newman可以理解为&#xff0c;没有…

shell脚本(五)

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

人口老龄化社区服务|基于springboot+vue的人口老龄化社区服务与管理平台(源码+数据库+文档)

目录 基于springbootvue的人口老龄化社区服务与管理平台 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&#xff0c;阿里云…

初识WGCLOUD - 监测磁盘空间还能使用多久

WGCLOUD是一款免费开源的运维监控软件&#xff0c;性能优秀&#xff0c;部署简单&#xff0c;轻巧使用&#xff0c;支持大部分的Linux和Windows、安卓、MacOS等平台安装部署 最近发布的新版本 v3.5.4&#xff0c;WGCLOUD新增了可以自动计算每个磁盘剩余空间的可使用天数&#x…

Linux各种并发服务器优缺点

本文旨在介绍针对“无并发C/S模型”改进的方法总结以及各种改进方法的优缺点&#xff0c;具体函数的实现并不介绍。 1. 无并发C/S模型 创建服务器流程分析&#xff1a; socket()创建服务器的监听套接字bind()将服务器给服务器的监听套接字绑定IP地址和Port端口号listen()设置…