news 2026/10/10 1:03:48

Android仿QQ课程设计源码实战:Socket长连接与MySQL架构解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Android仿QQ课程设计源码实战:Socket长连接与MySQL架构解析

简介:一份面向软件工程、计算机科学与技术等专业课程设计的Android Studio仿QQ即时通讯系统项目,包含完整源码、数据库与实验报告,可作期末大作业参考。项目模拟主流IM工具QQ的核心交互,覆盖登录验证、好友管理、消息收发等模块,技术难度中等,在教师指导下完成并获评98分,各功能单元经过多轮系统性测试,可在本地环境稳定运行。压缩包约5.68MB,共826个文件,以197个XML界面布局、87个Java核心源码、203个PNG图像资源为主,另有JSON配置、SQL/DB数据库文件、DOC与MD技术文档、Gradle构建脚本等,便于直接导入Android Studio编译运行。源码涉及客户端界面、网络通信、数据库读写、线程监听等关键实现,并配套数据库表结构及实验报告。已有48人学习浏览,可借鉴整体架构设计、模块拆分方法、数据库设计方案及测试验证思路,适合作为课程综合实践的完整参考。

1. Android Studio 仿 QQ 课程设计源码:先看清这套资源能做什么

Android 期末大作业、课程设计、源码这三个词凑到一起,最常被问的不是「怎么实现」,而是「下载下来能不能直接跑」。这套仿 QQ 即时通讯系统属于很典型的 Java Socket + MySQL 架构:Android 客户端负责界面和交互,服务端负责登录校验、消息转发、离线存储,数据库单独建库,实验报告把需求分析、ER 图、核心代码说明都写好了。适合两类人:一是还差几天就要交 Android 课程设计、需要快速跑通并理解每段代码的人;二是想拿一个能答辩的项目做二次改造、不想从零写 Socket 通信的人。先说结论:这套资源的难点不在代码量,而在环境和网络配置,后面几章把坑提前排掉。

2. 项目架构与核心选型:Socket 长连接、MySQL 存储与仿 QQ 的 UI 拆解

2.1 客户端模块划分:登录、会话列表、聊天窗口与联系人

客户端是典型的「仿 QQ」三段式结构:登录页放顶部 Logo、账号密码输入框和登录/注册按钮;主界面底部挂三个 Tab,通常叫消息、联系人、动态;消息 Tab 里是会话列表,每个 item 显示头像、昵称、最后一条消息和未读红点;点进某个会话后是聊天界面,左右气泡区分自己发的和对方发的,底部是输入框和发送按钮。这套结构在课程设计里几乎是模板,界面层代码集中在activity、adapter、fragment三个包,RecyclerView 负责列表,两个气泡 layout 通过适配器切换。

拿到源码后建议先做一件事:把res/layout目录下的界面文件数和实验报告里的功能结构图对照一遍。如果报告写了「头像裁剪」而布局里没有,或者报告截图里有「设置」页而代码里没有,答辩时被老师翻到就是硬伤。功能可以缩,但报告和代码必须对齐。这块不属于代码问题,属于「资源落地前的一致性检查」,越早做越省事。

2.2 服务端与数据库设计:为什么是 Java Socket + MySQL 而不是第三方 SDK

选型理由比功能列表更值得讲。很多同学拿到这种资源会问:为什么不用环信、融云,或者为什么不用 WebSocket?原因很简单,课程设计答辩老师盯的就那几个点:网络通信是不是自己写的、数据库增删改查是不是齐全、线程模型能不能讲清楚。Java Socket 虽然老,但每一步都能拆开讲:ServerSocket监听、accept接连接、每个客户端开一个处理线程、消息用换行分隔。WebSocket 在 Android 原生里要引 OkHttp 或 Java-WebSocket 依赖,查重和追问反而麻烦;第三方云 SDK 更惨,源码里看不到通信细节,被追问「消息投递失败怎么办」「服务端宕了离线消息存哪」基本答不上来。

数据库选 MySQL 也是冲着课程设计的要求去的——「数据库课程设计」要求里有明确的增删改查和表关系,MySQL 建三张表就足够支撑:用户表、好友表、聊天记录表。好友表维护用户之间的多对多关系,聊天记录表用is_read字段做未读和离线消息的标记,这个设计在答辩时比「把所有消息堆在一个字段里」好讲得多。

2.3 源码目录速览与实验报告结构

资源包通常分成四块:Android 客户端工程、Java 服务端工程、SQL 脚本、实验报告文档。客户端在app/src/main/java下按activity、adapter、socket、db、entity分包;服务端在server目录下,核心文件是ServerMain、ClientHandler、数据库工具类;sql目录放建库脚本;doc目录放实验报告,一般是 Word 或 Markdown。实验报告结构上也基本固定,五章:需求分析、总体设计、数据库设计、详细设计、测试截图。

数据库脚本是整个项目的地基,先看它长什么样。常见的初始化脚本类似下面这样:

CREATE DATABASE qq_chat DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE qq_chat; CREATE TABLE `user` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(30) NOT NULL UNIQUE COMMENT '登录账号', `password` VARCHAR(64) NOT NULL COMMENT '密码,课程设计里通常直接存明文或MD5', `nickname` VARCHAR(50) DEFAULT '' COMMENT '昵称', `avatar` VARCHAR(100) DEFAULT '' COMMENT '头像文件名' ) ENGINE=InnoDB; CREATE TABLE `friend` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `user_id` INT NOT NULL COMMENT '用户ID', `friend_id` INT NOT NULL COMMENT '好友ID', UNIQUE KEY uk_user_friend (`user_id`, `friend_id`) ) ENGINE=InnoDB; CREATE TABLE `chat_record` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `from_id` INT NOT NULL COMMENT '发送方ID', `to_id` INT NOT NULL COMMENT '接收方ID', `content` TEXT COMMENT '消息内容', `send_time` DATETIME DEFAULT CURRENT_TIMESTAMP, `is_read` TINYINT DEFAULT 0 COMMENT '0未读 1已读' ) ENGINE=InnoDB;

建库用utf8mb4而不是utf8,是为了让昵称和消息里的中文、表情都能正常存进去,这个细节直接影响后面会不会出现乱码问题。password注释里写「明文或 MD5」是因为这门课的重点在网络通信和数据库操作,不在密码加密上,报告里一般也只要求校验逻辑。friend表的联合唯一键能防止同一个好友被重复添加,chat_record的is_read字段是离线消息方案的依托——服务端发现接收方不在线时,把消息插进这张表,is_read保持 0,等对方登录后拉取。这三张表的关系和字段含义,建议在写报告时画一张 ER 图,答辩时基本必问。

3. 从导入到跑通:Android Studio 环境配置与数据库初始化全流程

3.1 导入工程与 Gradle 配置排查

老项目的导入比新建项目更容易卡在 Gradle 上。Android Studio 打开项目根目录后,先等 Sync 完成再动代码。常见的两种情况:一是项目用的 AGP 版本太老,新版 Android Studio 弹提示要升级;二是 Gradle 压缩包下载失败,Sync 报网络错误。前者不要急着点 Migrate,先看gradle-wrapper.properties里的版本号,再对照当前 Android Studio 的兼容范围决定升不升。后者直接把仓库源改成国内镜像,在项目根目录的build.gradle里加:

buildscript { repositories { maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } maven { url 'https://maven.aliyun.com/repository/public' } google() mavenCentral() } }

这是一次「移植 android studio 项目」时最常用的改法,把google()和mavenCentral()放在镜像源之后,Gradle 会优先走阿里云镜像,拉 AGP 插件和依赖库的速度会明显改善;如果项目还有单独的settings.gradle里的pluginManagement,同样要加一遍镜像源。镜像源只解决下载问题,不解决版本冲突。Sync 报「Unsupported Gradle version」时,优先看 JDK 版本是否匹配,AGP 7.x 需要 JDK 11,AGP 8.x 需要 JDK 17。查File → Project Structure → SDK Location里的 JDK 路径,确认用的是 Android Studio 自带的 JBR 而不是系统装了别的版本。

界面想换中文的话,Settings → Plugins 搜 Chinese 装一个语言包就行,菜单翻译不影响编译。这类源码包的英文注释一般也不多,重点把socket和db两个包看明白,中文不中文其实无所谓。

3.2 MySQL 建库脚本与连接参数设置

数据库部分是最容易被「少跑一步」的地方。先确认本机 MySQL 装的是 5.x 还是 8.x,这决定了 JDBC 驱动类名。执行脚本的常用命令:

mysql -u root -p source D:/path/to/init.sql;

source后面要写脚本的绝对路径,不要在C:\和D:\的路径分隔符上出错;执行完用SHOW TABLES;确认三张表都建出来了。如果之前跑过旧版本导致表结构冲突,就先DROP DATABASE qq_chat;再重新执行。然后打开服务端工程的数据库工具类,通常是DBUtil或JdbcUtil,核心是这一段:

Class.forName("com.mysql.cj.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/qq_chat" + "?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8"; String user = "root"; String password = "你的数据库密码";

MySQL 5.x 用com.mysql.jdbc.Driver,MySQL 8.x 必须换com.mysql.cj.jdbc.Driver,这个类名写错会直接报ClassNotFoundException。serverTimezone=Asia/Shanghai不设的话,连接时经常抛时区异常;characterEncoding=utf8是中文不乱码的第二个保险;useSSL=false是跳过本地开发环境的证书校验,课程设计场景不需要开 SSL。改完密码后,先跑一个简单的SELECT 1测试连接,别直接启动服务端,减少排查面。

3.3 启动服务端与模拟器联调

服务端用 IDEA 或 Eclipse 打开server目录,找到ServerMain直接运行,控制台保持窗口不关。客户端这边,模拟器访问宿主机有一个固定规律:不能用127.0.0.1,要用10.0.2.2。这是因为模拟器内部自成一套网络,10.0.2.2才是它眼里宿主机的地址。在客户端找服务端地址常量,一般在SocketClient或Constants里,改成:

public static final String SERVER_HOST = "10.0.2.2"; public static final int SERVER_PORT = 8888;

端口号以源码里的实际值为准,通常是8888、6666、9999中的一个,服务端和客户端保持一致即可。接着要检查AndroidManifest.xml,确认网络权限和明文流量声明:

<uses-permission android:name="android.permission.INTERNET"/> <application android:usesCleartextTraffic="true" ...>

targetSdk到 28 之后,系统默认禁止应用走明文 HTTP,Socket 直连 IP 也属于被拦的范围。不加usesCleartextTraffic="true"的话,App 点登录的瞬间就会闪退,日志里看见Cleartext HTTP traffic not permitted。这是这类源码包首次运行最高频的崩溃点,先加上再谈其他。模拟器跑起来之后,注册一个账号,如果能注册成功,说明客户端能连到服务端、服务端能写数据库,整条链路已经通了一大半。

3.4 验证清单:功能、操作方法与预期结果

跑通之后不要急着改代码,按下面这张表过一遍,缺什么心里有数,答辩要演示的也就这几个功能:

功能操作方法预期结果失败时的怀疑对象
注册登录页点注册,填账号密码服务端数据库user表多一条记录JDBC 连接参数、SQL 脚本是否执行
登录输入刚注册的账号跳转主界面,会话列表为空Socket 地址、服务端是否启动
单聊会话列表右上角添加好友,再点好友发消息对方能收到消息,自己界面出现右侧气泡在线用户表、消息协议
离线消息账号 B 退出登录,账号 A 发消息,B 再登录B 的会话列表出现未读消息is_read字段、离线拉取逻辑
聊天记录登录后重新进入某会话历史消息从数据库拉出来chat_record表、查询逻辑

这张表就是后面所有调试的索引。任何一个环节失败,先看它属于链路中的哪一段:注册失败是数据库问题,登录失败是 Socket 通信问题,消息收不到是转发问题。按段排查比从头读代码快得多。

4. 深入核心代码:登录鉴权、消息收发与数据库读写是怎么实现的

4.1 登录流程:从输入框到数据库校验

登录不是直接在 Android 端查数据库,而是把账号密码打包成一条消息发给服务端,由服务端校验后返回结果。这么设计是因为聊天功能本身就要走 Socket,登录走同一条通道,代码里只需要维护一套消息收发逻辑。客户端登录按钮的点击逻辑大概长这样:

private void doLogin() { String username = etUsername.getText().toString(); String password = etPassword.getText().toString(); Message msg = new Message(); msg.setType(Message.TYPE_LOGIN); msg.setFromId(-1); msg.setContent(username + "|" + password); SocketClient.getInstance().send(msg); }

这里Message是自定义实体类,字段一般有type、fromId、toId、content、sendTime。type用整数常量区分消息类型,登录是TYPE_LOGIN,聊天是TYPE_CHAT,登录结果是TYPE_LOGIN_RESULT。content用分隔符拼账号和密码,是课程设计里最常见的做法,因为简单直观;如果你觉得容易被问「为什么不用 JSON」,可以改成用JSONObject封装,成本很低,但答辩观感会好一些。注意setFromId(-1)表示尚未登录,服务端校验通过后会在返回消息里带上真实的用户 ID。

服务端收到TYPE_LOGIN消息后的处理逻辑,核心是查库:

String[] parts = msg.getContent().split("\\|"); User u = userDao.findByUsernameAndPassword(parts[0], parts[1]); if (u != null) { onlineUsers.put(u.getId(), socket); send(msg, "SUCCESS|" + u.getId() + "|" + u.getNickname()); } else { send(msg, "FAIL|用户名或密码错误"); }

findByUsernameAndPassword对应一条最基础的 JDBC 查询,拼 SQL、传参数、拿ResultSet、封装成User。这里有个值得注意的点:onlineUsers是一个线程安全的 Map,key 是用户 ID,value 是对应的 Socket 输出流,登录成功就把这个用户标记为在线,后面聊天转发全靠它。这段逻辑建议在报告里画一张时序图,从按钮点击到数据库校验到返回结果,能画清楚基本就稳了。

4.2 消息收发:Socket 线程模型与消息解析协议

消息收发是这套源码里最核心、也最容易出 bug 的部分。客户端在SocketClient里维护两个线程:一个读线程循环readLine,一个写线程负责发送。服务端则是一个ServerSocket主线程accept新连接,每接一个客户端就开一个ClientHandler线程。关键代码是这样的:

public void run() { String line; while ((line = in.readLine()) != null) { Message msg = JSON.parseObject(line, Message.class); if (msg.getType() == Message.TYPE_CHAT) { Socket target = onlineUsers.get(msg.getToId()); if (target != null) { BufferedWriter w = new BufferedWriter( new OutputStreamWriter(target.getOutputStream())); w.write(JSON.toJSONString(msg)); w.newLine(); w.flush(); } else { chatDao.insertOffline(msg); } } } }

这里有两个关键点。第一,每条消息以换行符\n结尾,读取端用readLine()才能一次拿一条完整消息,这是 Socket 文本协议最基础也最容易被忽略的约定。第二,转发前先查onlineUsers,目标在线就直接写对方的输出流,不在线就把消息插进chat_record表,is_read保持默认 0,等对方登录后再拉。写输出流时write、newLine、flush必须一起出现,flush是真正把数据推给网络的步骤,只调write会导致数据积在缓冲区里,对方一直收不到。

服务端维护在线用户表用的是ConcurrentHashMap,线程安全的 Map,key 建议统一用Integer。这里有个隐蔽的坑:登录时服务端拿到的是u.getId(),是Integer,而客户端后续消息里传的fromId和toId如果是从界面输入框解析出来变成字符串,查 Map 时类型不匹配,get(null)永远返回 null,消息就永远走离线分支。用HashMap的话 key 类型不一致还能撞上,ConcurrentHashMap直接返回 null。调试时看到「消息发出去对方收不到」第一反应就查这个消息类型。

4.3 聊天记录存取:SQLite 还是 MySQL,离线消息怎么处理

课程设计的要求一般只看 MySQL,聊天记录统一落 MySQL 就够了。本地 SQLite 可以做一个只读缓存,但答辩时被问「为什么本地也要存」不好答——如果只是为了看历史记录,登录后从 MySQL 拉更合理。我一般建议聊天记录只走 MySQL,本地SQLite只存当前登录用户 ID 和服务器地址,减少双写一致性的麻烦。报告里写「使用 SQLite 保存本地登录状态」,比写「本地缓存聊天记录」少很多追问。

离线消息的拉取逻辑发生在登录成功之后,代码模式基本是固定的:

List<ChatRecord> list = chatDao.selectByToIdAndUnread(userId); for (ChatRecord r : list) { Message m = new Message(); m.setType(Message.TYPE_CHAT); m.setFromId(r.getFromId()); m.setContent(r.getContent()); deliver(m); } chatDao.markRead(userId);

先把is_read = 0的记录全部查出来,逐条封装成Message分发到界面,最后统一把已读标记置 1。注意顺序不能反过来,先markRead再查询的话,消息可能漏掉。deliver方法是把消息投递给聊天界面的回调接口,通常用Handler或LiveData切回 UI 线程,更新会话列表和聊天记录。这段逻辑如果讲清楚,答辩时「离线消息怎么保证不丢」的问题就基本有底了:发送方不管对方在不在线都先落库,接收方登录后统一拉取未读。

5. 避坑指南:这类课程设计最常见的 5 个翻车点

这类资源包 90% 的问题集中在固定的几个点上,按现象排查比从头读源码高效。我按两类归纳:一类是环境层面的,连不上、乱码、闪退;一类是通信和答辩层面的,消息丢失、报告与源码不符。每一条都是实际跑过的记录,按「现象 → 原因 → 解决」写。

5.1 环境类:模拟器连接、中文乱码与明文流量

现象 1:模拟器点击登录后卡住,Logcat 报java.net.ConnectException: Connection refused。

原因:客户端把服务器地址写成了127.0.0.1或localhost。在 Android 模拟器里,这两个地址指向模拟器自己,而不是你的电脑。服务端跑在电脑上,客户端自然连不上。
解决:模拟器一律用10.0.2.2访问宿主机;真机调试的话,改成电脑的局域网 IP,比如192.168.x.x,并且要保证手机和电脑连的是同一个 WiFi。检查方法很简单,电脑上ipconfig看 IPv4 地址,手机浏览器访问http://192.168.x.x:服务端端口,能通再改代码。

现象 2:注册的昵称是中文,数据库里看到的却是??。

原因:建库时没指定字符集,或者 JDBC URL 里少了characterEncoding=utf8,又或者表结构本身是默认的latin1。三个层面有一处不一致,中文就存不进去。
解决:先用第 2 章的建库 SQL 重建数据库,确保建库语句带DEFAULT CHARACTER SET utf8mb4;JDBC URL 加characterEncoding=utf8;如果有已经存在的表,用ALTER TABLE user CONVERT TO CHARACTER SET utf8mb4;补救。检查时可以在 MySQL 里执行SHOW VARIABLES LIKE 'character_set%';看整体状态。

现象 3:App 一点登录就闪退,日志里有Cleartext HTTP traffic not permitted。

原因:targetSdk大于等于 28 时,Android 默认禁止应用发明文 HTTP 请求。Socket 直连10.0.2.2这种裸 IP 属于被拦的明文流量。
解决:在AndroidManifest.xml的application标签加android:usesCleartextTraffic="true"。有些源码包只加了INTERNET权限,没有加这个属性,所以拿到手要先确认。用真机调试同样要加,局域网 IP 也属于明文流量。

5.2 通信类与答辩前置:消息丢失、报告截图不符

现象 4:A 发消息后自己界面立刻出现了气泡,B 那边毫无反应,服务端控制台也没报错。

原因:这是两个问题叠加的结果。一是 A 在界面层「假发送」,不管服务端有没有确认都先把气泡渲染上;二是服务端转发时可能没flush,或者onlineUsers里根本没有 B 的记录。B 不在线的话消息走了离线分支插库,但界面层的会话列表没刷新,看起来就像丢了。
解决:按顺序排查。先看服务端有没有进入TYPE_CHAT分支,打印日志确认toId是什么;再看在线用户表里 B 的 key 是Integer类型还是字符串类型,类型不一致会导致查不到;最后确认write之后有没有newLine和flush。如果都正常,再看客户端的离线拉取逻辑有没有写到deliver,因为 B 重新登录后消息可能已经进库了,只是界面没刷新。

现象 5:实验报告提交后被老师打回,要求现场重新演示,结果现场登录失败。

原因:报告里的截图和运行结果用的是资源包自带的旧图,不是自己跑通的。源码里的数据库密码、服务器地址还是原作者的,答辩时换了机器或改了环境,自然起不来。
解决:拿到资源先完整跑一遍,把注册、登录、单聊、离线消息四个场景全部重新截图,替换报告里的旧截图。数据库表字段改过的话,ER 图也要同步改。报告是给老师看的,运行环境是你答辩时用的,两者必须严格一致。这是血泪经验,资源包里的报告只能当模板,不能直接交。

6. 从单机 Demo 到局域网多人联调:让作业更像工程的改造思路

如果想让这个项目在答辩时脱颖而出,最简单的加分项是把「模拟器 + 单机」改成「两台真机 + 局域网联调」。改造量不大,核心就是把服务器地址抽成配置类,然后让服务端能同时处理两个客户端的连接。

public class ServerConfig { // 电脑上 ipconfig 查到的 IPv4 地址,真机与电脑必须连同一 WiFi public static final String HOST = "192.168.x.x"; public static final int PORT = 8888; }

把客户端代码里所有写死的10.0.2.2全部替换成读取ServerConfig.HOST,同时检查服务端ServerMain在线用户表的逻辑——确保它用的是ConcurrentHashMap<Integer, Socket>而不是普通HashMap,因为多客户端同时登录、同时收发消息时,线程安全是必须保证的。服务端启动后建议打印一句本机 IP,方便真机填地址时核对:

System.out.println("Server started at " + InetAddress.getLocalHost().getHostAddress() + ":" + port);

这个输出在答疑时会给你省很多时间。演示时开两台真机或两个模拟器,A 登录后给 B 发消息,B 的会话列表未读数加 1;把 B 的 App 彻底关掉,A 再发一条,然后重新打开 B 登录,这条消息出现在聊天记录里——这三个场景对应「在线实时收发」和「离线消息不丢」两个硬指标,比单机演示有说服力得多。

从那以后我每次拿到这种带数据库的课程设计源码,都不会先看功能列表,而是先建库、跑服务端、连客户端,完整走一遍三件套,确认跑通了再改自己的数据库密码和服务器地址,最后把运行截图逐张替换进报告。流程走熟了,这类项目基本一周内能从导入到交稿全部搞定。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 1:02:43

基于PCA9422与PIC18F86K22的嵌入式电源管理与动态调压实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/10 1:02:41

低功耗嵌入式系统设计:MK60与PCA9422电源管理实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/10 1:02:16

PCA9422 + dsPIC33FJ256GP710A:软硬协同的多路电源管理设计实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/10 1:02:04

PCA9422与PIC18F8722协同实现嵌入式完整电源管理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/10 1:00:35

pstack-claude:让大模型读懂Linux进程调用栈的CLI调试工具

1. 项目概述&#xff1a;pstack-claude 是什么&#xff0c;它解决的是哪类开发者的真实痛点&#xff1f;pstack-claude 这个名字乍看像一个拼接词&#xff0c;但拆开来看就非常有指向性&#xff1a;“pstack”是 Linux 系统中一个真实存在的诊断工具&#xff0c;用于打印指定进…

作者头像 李华
网站建设 2026/10/10 0:57:53

数据库系统概论期末试题解析:高频考点与避坑指南

简介&#xff1a;这份《数据库系统概论复习期末试题及答案》PDF面向高校计算机专业学生及备考数据库相关课程的考生&#xff0c;用于期末冲刺与知识点自测。内容以单项选择题、填空题为主&#xff0c;覆盖DBMS核心地位、三级模式与两级映像、E-R模型、关系代数、SQL授权与建表、…

作者头像 李华