基于MFC和WinSock的简易聊天室程序(附完整源码)
本文使用Windows C网络编程和多线程编程实现一个简单的聊天室程序。该程序由服务器端和客户端两部分组成。服务器端负责客户端的上线、离线以及转发各个客户端发来的消息。客户端向服务器发送信息从服务器接收信息以及显示信息到客户端界面。1.创建服务器端界面首先创建项目。打开Vistual Stdio创建一个MFCMicrosoft Foundation Classes项目应用程序类型选择基于对话框在高级功能中勾选Windows套接字完成Winsock DLL库的初始化。项目名称改为ChatServer。创建好项目后在菜单栏中选择视图其它窗口找到资源视图。打开下图所示文件IDD_CHATSERVER_DIALOG就是我们创建的服务器端的界面。删除原来的所有控件。选择对话框右键打开属性将文字描述对话框标题改为“聊天室服务器端”边框选择“对话框外框”。再次打开视图选择工具箱为聊天界面添加控件。下面使用到的几个控件。Button是按钮Edit Control是文本编辑框Static Text是静态的文本IP Address Control用于编辑Ip地址。依照下图完成控件的添加除基本功能外可以自由发挥。除了静态的控件外其余控件的ID及属性见下表。控件名ID其它属性编辑框已连接客户端右侧IDC_ECIT_CLIENTS只读true编辑框中间较大IDC_EDIT_MSG只读true多行true垂直滚动trueIP地址IDC_IPADDRESS编辑框PORT右侧IDC_EDIT_PORT按钮启动服务器IDC_START文字描述按钮退出程序IDC_EXIT文字描述为了方便获取和设置各个控件的值我们为控件添加关联变量。在解决方案资源管理器中右键点击项目ChatServer打开“类向导”。确认项目名称为ChatServer在“类名”中选择CChatServerDlg单击“成员变量”标签。可以看到之前创建的控件及其ID。选择控件点击“添加变量”为控件添加关联变量。弹出的“添加控件变量”对话框如下。分别注意类型名称和变量类型。类别分为值和控件值的作用是同步控件显示的数据可以选择如CStringintdouble等基本变量类型它通过UpdateData()函数实现与控件的通信UpdateData(TRUE)将控件中的数据读取并保存到关联的变量中。UpdateData(FALSE)将变量中的值写入并显示在关联的控件上。控件的作用则是直接操控控件本身例如启用、禁用、修改文字等它通过调用控件的成员函数来实现对控件的操控。名称和变量类型则分别对应创建的变量名称和数据类型。下表为需要添加的关联变量。ID类别变量名变量类型IDC_IPADDRESS控件m_ipServerCIPAddressCtrlIDC_EDIT_PORT值m_nPortunsigned intIDC_EDIT_CIENTS值m_nClientsunsigned intIDC_EDIT_MSG控件m_edtMsgCEdit添加结束后我们可以在对话框类CChatServerDlg的定义中找到相应变量如下。unsigned int m_nClients; CIPAddressCtrl m_ipServer; unsigned int m_nPort; CEdit m_edtMsg;同时在ChatServerDlg.cpp中也可以找到如下函数。它将相应的关联变量和控件建立联系。void CChatServerDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT_CLIENTS, m_nClients); DDX_Control(pDX, IDC_IPADDRESS, m_ipServer); DDX_Text(pDX, IDC_EDIT_PORT, m_nPort); DDX_Control(pDX, IDC_EDIT_MSG, m_edtMsg); }最后为了避免每次启动程序都要重新填写IP地址、端口等数据可以为这两个控件设置初始值。找到并打开文件ChatServerDlg.cpp找到对话框初始化函数OnInitDialog()在//TODO一行下添加如下代码。// TODO: 在此添加额外的初始化代码 m_ipServer.SetAddress(127, 0, 0, 1); m_nPort 8888; m_nClients 0; UpdateData(false);将IP地址初始化为127.0.0.1端口号初始化为8888用户数量初始化为0最后将变量值显示到对应的控件上。运行程序如下。2.创建客户端界面客户端界面的创建方法和服务器端基本一致。创建MFC项目选择基于对话框勾选Windows套接字项目名称为ChatClient。对话框界面和控件如下。控件名ID其它属性编辑框中间较大IDC_EDIT_MSG只读true多行true垂直滚动true编辑框左下方IDC_EDIT_SENDIP地址IDC_IPADDRESS编辑框服务器端口IDC_EDIT_PORT按钮登录IDC_LOGIN文字描述按钮退出程序IDC_EXIT文字描述按钮发送IDC_SEND文字描述为控件添加关联变量如下。ID类别变量名变量类型IDC_IPADDRESS控件m_ipServerCIPAddressCtrlIDC_EDIT_PORT值m_nPortunsigned intIDC_EDIT_SEND值CStringm_strSendIDC_EDIT_MSG控件CEditm_edtMsg对话框初始化代码如下。// TODO: 在此添加额外的初始化代码 m_ipServer.SetAddress(127, 0, 0, 1); m_nPort 8888; UpdateData(false);运行程序如下。3.服务器端编程1.对话框类中添加数据成员需要在对话框类CChatServerDlg中使用向量vector在头文件ChatServerDlg.h文件开始部分加入下面两行代码。包含相应的头文件和命名空间。#includevector using namespace std;服务器要存储每个连接的客户端的信息首先定义一个保存客户端信息的类ClientItem之后使用vector保存所有客户端。在ChatServerDlg.h文件中找到对话框类CChatServerDlg的定义处在上方添加ClientItem的定义。class CChatServerDlg; class ClientItem { public: SOCKET cltSocket; CString cltIP; int cltPort; CChatServerDlg* pChatDlg; ClientItem() { cltPort 8888; cltSocket INVALID_SOCKET; pChatDlg NULL; } };注意到ClientItem中使用了CChatServerDlg类将其声明提前。可以看出保存的客户端信息有对应的socket、IP地址、端口。为了能在ClientItem类中访问对话框类的成员保存了一个对话框类的地址pChatDlg。在CChatServerDlg类末尾加入以下两个属性。SOCKET m_listenSocket; vectorClientItem* m_clients;分别为监听套接字和保存客户端信息的向量。同时在ChatServerDlg.cpp中找到CChatServerDlg类的构造函数的定义加入以下代码。m_listenSocket INVALID_SOCKET;2.为“启动服务器”按钮添加功能。打开“类向导”对话框选择项目ChatServer选择类CChatServerDlg选择“命令”标签找到按钮ID——IDC_START选中在“消息”中选择BN_CLICKED该通知码在用户点击对应按钮时向父窗口发送对应的按钮ID和通知码点击“添加处理程序”添加按钮的消息响应函数OnClickedStart()。同关联变量一样可以在对话框类CChatServerDlg的定义里找到函数声明。afx_msg void OnClickedStart();afx_msg是一个宏表明这是一个消息响应函数。在ChatServerDlg.cpp中也可以找到如下代码。第五行表明IDC_STRAT控件在收到BN_CLICKED消息时会执行相应的函数即建立联系。BEGIN_MESSAGE_MAP(CChatServerDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_START, CChatServerDlg::OnClickedStart) ON_MESSAGE(WM_UPDATE_MSG, OnUpdateMsg) ON_BN_CLICKED(IDC_EXIT, CChatServerDlg::OnClickedExit) END_MESSAGE_MAP()那么接下来我们来完成消息响应函数OnClickedStart()的定义将其添加在ChatServerDlg.cpp的末尾。参见注释理解代码。void CChatServerDlg::OnClickedStart() { // TODO: 在此添加控件通知处理程序代码 UpdateData(true); //将对话框中的值保存到相应的关联变量里 DWORD dwIP; //IP地址 m_ipServer.GetAddress(dwIP); //获取控件中的IP地址 //创建监听套接字 m_listenSocket socket(AF_INET, SOCK_STREAM, 0); if (m_listenSocket INVALID_SOCKET) { AfxMessageBox(_T(创建socket失败!!!)); //弹出一个提示框 return; } //绑定IP和端口 sockaddr_in serverAddr { 0 }; serverAddr.sin_family AF_INET; serverAddr.sin_port htons(m_nPort); serverAddr.sin_addr.s_addr htonl(dwIP); if (bind(m_listenSocket, (sockaddr*)serverAddr, sizeof(serverAddr)) -1) { AfxMessageBox(_T(绑定失败!!!)); return; } //开始监听 if (INVALID_SOCKET listen(m_listenSocket, 5)) { AfxMessageBox(_T(监听失败!!!)); return; } //调用控件变量的成员函数在窗口上显示文本 m_edtMsg.SetWindowTextW(_T(服务器已启动!!!\r\n)); //GetDlgItem()函数获得指向参数(控件ID)控件的临时指针 //EnableWindow()函数用于启用/禁用控件,false禁用,true启用 GetDlgItem(IDC_START)-EnableWindow(false); //创建监听线程this是对话框的指针 HANDLE h CreateThread(NULL, 0, AccpThreadProc, this, 0, NULL); if (h ! NULL) CloseHandle(h); return; }3.创建监听线程函数编写监听线程的函数首先在CChatServerDlg类中声明。static DWORD WINAPI AccpThreadProc(LPVOID pParam);然后在ChatServerDlg.cpp中给出定义。DWORD WINAPI CChatServerDlg::AccpThreadProc(LPVOID pParam) { CChatServerDlg* thisDlg (CChatServerDlg*)pParam; while (true) { sockaddr_in clientAddr { 0 }; int iLen sizeof(sockaddr_in); //取出队列头部的请求,并创建专门与该客户端通信的套接字 SOCKET accSock accept(thisDlg-m_listenSocket, (sockaddr*)clientAddr, iLen); if (accSock INVALID_SOCKET) { AfxMessageBox(_T(监听失败!!!)); return 0; } //创建ClientItem对象,保存客户端信息 ClientItem* pClient new ClientItem(); pClient-cltSocket accSock; char IP[20]; //点分十进制格式IP地址 inet_ntop(AF_INET, (void*)clientAddr.sin_addr, IP, 16); //转换IP地址格式 pClient-cltIP.Format(_T(%S), IP); //保存IP地址 pClient-cltPort clientAddr.sin_port; //保存端口号 pClient-pChatDlg thisDlg; //保存服务器对话框 thisDlg-m_clients.push_back(pClient); //添加到向量中 thisDlg-m_nClients; //增加登录客户端数 CString msgIP(pClient-cltIP); CString msgPort; msgPort.Format(_T(:%d), pClient-cltPort); CString msg msgIP msgPort 登录; //编辑即将显示的文本 //向对话框发送消息,更新界面 //::(全局作用域符):强制指定标识符变量、函数、类型属于全局命名空间Global Namespace而非当前局部作用域或某个特定的命名空间/类。 //SendMessage:将对应消息WM_UPDATE_MSG添加进目标窗口thisDlg并等待 //GetSafeHwnd:安全地获取对应窗口的句柄 //WM_UPDATE_MSG:自定义的消息ID //后面两个为该消息对应相应函数的参数 ::SendMessage(thisDlg-GetSafeHwnd(), WM_UPDATE_MSG, NULL, (LPARAM)msg); //创建一个接收用户消息的线程 HANDLE h CreateThread(NULL, 0, RecvThreadProc, pClient, 0, NULL); if (h ! NULL) CloseHandle(h); return 0; } }4.创建接收数据线程函数为接收用户消息的线程编写线程函数先在CChatServerDlg类中声明。static DWORD WINAPI RecvThreadProc(LPVOID pParam);在ChatServer.cpp给出定义。DWORD WINAPI CChatServerDlg::RecvThreadProc(LPVOID pParam) { ClientItem* thisClient (ClientItem*)pParam; while (true) { TCHAR buffer[256] { 0 }; int nRecv recv(thisClient-cltSocket, (char*)buffer, sizeof(buffer), 0); if (nRecv 0) { //-1:网络出错;0:对方关闭连接 removeClient(thisClient-pChatDlg-m_clients, thisClient); return 0; } //在消息前加上用户的IP地址和端口 CString strPort; strPort.Format(_T(%d), thisClient-cltPort); CString msg thisClient-cltIP - strPort : buffer; TCHAR sendBuf[256] { 0 }; _tcscpy_s(sendBuf, 256, msg); vectorClientItem*::iterator it thisClient-pChatDlg-m_clients.begin(); //挨个发送消息 for (; it ! thisClient-pChatDlg-m_clients.end(); it) { ClientItem* pClient *it; int bufLen _tcslen(sendBuf) * sizeof(TCHAR); int len send(pClient-cltSocket, (char*)sendBuf, bufLen, 0); if (len 0) { removeClient(thisClient-pChatDlg-m_clients, pClient); } } } return 0; }5.添加removeClient()函数添加上面用到的removeClient()函数为了使用方便也定义为类的静态函数。static void removeClient(vectorClientItem*clients, ClientItem* theClient);void CChatServerDlg::removeClient(vectorClientItem*clients, ClientItem* theClient) { --(theClient-pChatDlg-m_nClients); //客户端数量减1 //向对话框发送消息,通知该客户端离线 CString msgIP(theClient-cltIP); CString msgPort; msgPort.Format(_T(:%d), theClient-cltPort); CString msg msgIP msgPort 离开; ::SendMessage(theClient-pChatDlg-GetSafeHwnd(), WM_UPDATE_MSG, NULL, (LPARAM)msg); vectorClientItem*::iterator it; for (it clients.begin(); it ! clients.end(); it) { ClientItem* pClient *it; if (pClient-cltSocket theClient-cltSocket) { clients.erase(it); break; } } delete theClient; //删除客户端 }6.对话框自定义消息响应函数想要发送自定义消息需要定义消息宏、添加消息响应函数以及完成消息映射。在ChatServerDlg.cpp文件开始部分加入以下消息宏定义。#define WM_UPDATE_MSG WM_USER100WM_USER1024是一个界限小于WM_USER的ID是系统使用的因此我们使用WM_USER100作为自定义的消息ID。在CChatServerDlg类中给出消息响应函数的声明。afx_msg LRESULT OnUpdateMsg(WPARAM wParam, LPARAM lParam);函数格式是固定的。定义如下。LRESULT CChatServerDlg::OnUpdateMsg(WPARAM wParam, LPARAM lParam) { CString* strMsg (CString*)lParam; int len m_edtMsg.GetWindowTextLength(); //原来编辑框中文本长度 m_edtMsg.SetSel(len, len); //表示选中(len,len)之间的文字,并将光标挪到那里,同时保证光标可见 m_edtMsg.ReplaceSel(*strMsg _T(\r\n)); //用新文本替换当前被选中的文本,这里是直接添加 UpdateData(false); return 0; }最后要完成消息映射在ChatServerDlg.cpp中找到如下代码并完成添加如下。BEGIN_MESSAGE_MAP(CChatServerDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_START, CChatServerDlg::OnClickedStart) ON_MESSAGE(WM_UPDATE_MSG, OnUpdateMsg) //添加的内容 ON_BN_CLICKED(IDC_EXIT, CChatServerDlg::OnClickedExit) END_MESSAGE_MAP()ON_MESSAGE是一个通用消息映射宏绑定消息和对应的处理函数。7.添加“退出程序”按钮的消息响应函数使用类向导添加消息响应函数在函数中添加一下代码。void CChatServerDlg::OnClickedExit() { // TODO: 在此添加控件通知处理程序代码 CDialogEx::OnCancel(); }这里直接调用基类的成员函数来关闭对话框。8.添加析构函数在CChatServerDlg类的构造函数声明下添加析构函数的声明。再添加函数定义如下。CChatServerDlg::~CChatServerDlg() { if (m_listenSocket ! INVALID_SOCKET) closesocket(m_listenSocket); vectorClientItem*::iterator it; for (it m_clients.begin(); it ! m_clients.end(); it) { ClientItem* pClient *it; delete pClient; } m_clients.clear(); }4.客户端编程1.对话框类中添加数据成员在CChatClientDlg类中添加负责与服务器通信的socket。SOCKET m_Socket在构造函数里完成初始化。m_Socket INVALIDE_SOCKET;2.添加“登录”按钮的消息相应函数在类向导中添加消息相应函数完善函数定义如下。void CChatClientDlg::OnClickedLogin() { // TODO: 在此添加控件通知处理程序代码 UpdateData(true); DWORD dwIP; m_ipServer.GetAddress(dwIP); m_Socket socket(AF_INET, SOCK_STREAM, 0); if (m_Socket INVALID_SOCKET) { AfxMessageBox(_T(创建socket失败!!!)); return; } sockaddr_in serverAddr; serverAddr.sin_family AF_INET; serverAddr.sin_port htons(8888); serverAddr.sin_addr.s_addr htonl(dwIP); if (connect(m_Socket, (sockaddr*)serverAddr, sizeof(serverAddr)) -1) { AfxMessageBox(_T(连接失败!!!)); return; } m_edtMsg.SetWindowTextW(_T(登录成功!!!\r\n)); GetDlgItem(IDC_LOGIN)-EnableWindow(false); GetDlgItem(IDC_SEND)-EnableWindow(true); HANDLE h CreateThread(NULL, 0, RecvThreadProc, this, 0, NULL); if (h ! NULL) CloseHandle(h); }3.创建接收数据线程的函数在CChatClientDlg类中给出声明。static DWORD WINAPI RecvThreadProc(LPVOID pParam);定义如下。DWORD WINAPI CChatClientDlg::RecvThreadProc(LPVOID pParam) { CChatClientDlg* thisDlg (CChatClientDlg*)pParam; while (true) { TCHAR buffer[256] { 0 }; int nRecv recv(thisDlg-m_Socket, (char*)buffer, sizeof(buffer), 0); if (nRecv 0) { closesocket(thisDlg-m_Socket); thisDlg-GetDlgItem(IDC_LOGIN)-EnableWindow(true); thisDlg-GetDlgItem(IDC_SEND)-EnableWindow(false); AfxMessageBox(_T(服务器失去联系请稍后再试)); break; } CString msg(buffer); ::SendMessage(thisDlg-GetSafeHwnd(), WM_UPDATE_MSG, NULL, (LPARAM)msg); } return 0; }4.对话框自定义消息响应函数消息的宏定义如下。#define WM_UPDATE_MSG WM_USER100在CChatClientDlg类中给出声明如下。LRESULT OnUpdateMsg(WPARAM w, LPARAM l);定义如下。LRESULT CChatClientDlg::OnUpdateMsg(WPARAM w, LPARAM l) { CString* strMsg (CString*)l; int len m_edtMsg.GetWindowTextLength(); m_edtMsg.SetSel(len, len); m_edtMsg.ReplaceSel(*strMsg _T(\r\n)); return 0; }完成消息映射。BEGIN_MESSAGE_MAP(CChatClientDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_LOGIN, CChatClientDlg::OnClickedLogin) ON_MESSAGE(WM_UPDATE_MSG, OnUpdateMsg) //添加行 ON_BN_CLICKED(IDC_SEND, CChatClientDlg::OnClickedSend) ON_BN_CLICKED(IDC_EXIT, CChatClientDlg::OnClickedExit) END_MESSAGE_MAP()5.为“发送”按钮添加消息响应函数在类向导中添加消息响应函数完善定义如下。void CChatClientDlg::OnClickedSend() { // TODO: 在此添加控件通知处理程序代码 UpdateData(true); TCHAR buffer[256] { 0 }; _tcscpy_s(buffer, 256, m_strSend); if (_tcslen(buffer) 0) { return; } int len send(m_Socket, (char*)buffer, _tcslen(buffer) * sizeof(TCHAR), 0); if (len 0) { closesocket(m_Socket); GetDlgItem(IDC_LOGIN)-EnableWindow(true); GetDlgItem(IDC_SEND)-EnableWindow(false); AfxMessageBox(_T(服务器失去连接请稍后再试)); } m_strSend ; UpdateData(false); }6.添加“退出程序”按钮的消息响应函数与服务器端的操作方法一致。7.添加析构函数CChatClientDlg::~CChatClientDlg() { if (m_Socket ! INVALID_SOCKET) closesocket(m_Socket); }写在最后非常感谢您能耐心读完这篇文章。如果文中有任何表述不准确、代码不够优雅或逻辑有误之处恳请各位大佬在评论区不吝指正我一定虚心学习、及时修正。如果您觉得这篇文章对您有所帮助不妨点个赞 并关注我您的每一次鼓励都是我继续输出的动力。后续我还会分享更多的内容欢迎常来一起交流一起成长 ——不想干活的十一

相关新闻

如何在Windows上优雅地管理Android应用?APK Installer场景化使用指南

如何在Windows上优雅地管理Android应用?APK Installer场景化使用指南

如何在Windows上优雅地管理Android应用?APK Installer场景化使用指南 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否经常需要在Windows电脑上测试An…

2026/10/15 18:25:42 阅读更多 →
DeepSeek V4 Pro 新手极速上手指南

DeepSeek V4 Pro 新手极速上手指南

在本地运行大语言模型曾经是很多开发者的“梦想项目”,但往往止步于复杂的依赖配置和令人头秃的环境报错。随着模型量化技术的成熟和推理引擎的优化,如今在消费级显卡甚至纯 CPU 环境下部署高性能模型已成为可能。当你不再依赖云端 API,而是将…

2026/10/13 16:25:41 阅读更多 →
如何通过Wand-Enhancer实现WeMod本地功能增强与远程控制

如何通过Wand-Enhancer实现WeMod本地功能增强与远程控制

如何通过Wand-Enhancer实现WeMod本地功能增强与远程控制 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer Wand-Enhancer是一个开源的本地客户端增强…

2026/10/16 6:17:34 阅读更多 →

最新新闻

Flask+Redis+MySQL打造电商购书平台:抽奖与积分系统实战解析

Flask+Redis+MySQL打造电商购书平台:抽奖与积分系统实战解析

如果你搜Python练手项目,排名靠前的大概率是图书管理系统、爬虫、记账本这类。但真正能帮你把电商知识串起来的项目,至少要包含商品、订单、支付、库存,而线上购书平台如果再加上抽奖和积分兑换,基本就是把运营玩法也补齐了。我前…

2026/10/16 7:58:16 阅读更多 →
AI产品经理的决策框架:从Agent落地看人机协同设计

AI产品经理的决策框架:从Agent落地看人机协同设计

1. 这不是技术课,是AI产品决策现场的复盘笔记做了几个 Agent 项目后,我发现:真正拉开 AI 产品经理差距的,不是技术——这句话我是在凌晨三点改完第三版 workflow 编排逻辑、盯着日志里反复失败的 tool calling 调用链发呆时写下的…

2026/10/16 7:58:16 阅读更多 →
毕业论文AI率41%到9%:降AI的48小时自救与四步拆骨法

毕业论文AI率41%到9%:降AI的48小时自救与四步拆骨法

说实话,我从来没觉得“AI率”三个字会以那种方式砸在我脸上。周一上午十点,我正坐在实验室改论文的参考文献格式,手机屏幕弹出一条消息,是导师转发的学院系统检测报告截图。我那篇熬了快一个月的毕业论文初稿,疑似AI生…

2026/10/16 7:58:16 阅读更多 →
Python学习笔记:从虚拟环境到调试的完整成长路径

Python学习笔记:从虚拟环境到调试的完整成长路径

每次有人问我“Python学到什么程度算入门”,我的回答从来都是:去翻你自己的Python学习笔记。如果笔记里全是复制粘贴的代码,说明还在抄作业阶段;如果里面有报错记录、踩坑复盘、以及你自己写下的注释,那才算真正开始会…

2026/10/16 7:58:16 阅读更多 →
迭代学习控制开源代码:让重复作业系统一次比一次精准

迭代学习控制开源代码:让重复作业系统一次比一次精准

简介:迭代学习控制(ILC)是一类面向重复性任务的控制策略,核心思想是通过多次迭代修正控制输入,逐步逼近期望输出,在机器人、自动化生产线、航空航天等领域均有广泛应用。这份开源代码以单个MATLAB的m文件呈…

2026/10/16 7:58:16 阅读更多 →
nvidia-smi命令找不到?从驱动到容器彻底排查与修复指南

nvidia-smi命令找不到?从驱动到容器彻底排查与修复指南

“nvidia-smi: command not found”大概是 Linux 装显卡驱动时最经典、也最让人摸不着头脑的报错。我第一次遇到是在一台刚装完系统的服务器上,当时还以为是显卡坏了,折腾半天才发现只是驱动没装上。后来搞多了就明白,这个报错本身不复杂&…

2026/10/16 7:57:16 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

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

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/15 9:49:14 阅读更多 →