Linux网络:网络套接字-TCP回显服务器——多进程/线程池(生产者消费者模型)
1.多进程版本
这里选择创建子进程,让子进程再创建子进程。父进程等待子进程,子进程的子进程处理业务逻辑。因为子进程是直接退出,子进程的子进程变成孤儿进程被系统管理,所以父进程在等待的时候不是阻塞等待的,所以可以处理多条链接请求。或者可以忽略SIGCHID信号让子进程不需要等待。
服务端
pragma once #include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#include<fcntl.h>
#include<signal.h>
#include<sys/wait.h>#define DEF_PORT 8081class TcpSever
{private:int port;int listen_sock;//监听套接字public: TcpSever(int _port=DEF_PORT):port(_port),listen_sock(-1){}void InitSever(){listen_sock=socket(AF_INET,SOCK_STREAM,0);//IPV4流式套接if(listen_sock<0){std::cerr<<"监听套接字创建失败"<<std::endl;exit(-1);}//绑定struct sockaddr_in local;memset(&local,'\0',sizeof(local));//初始化结构体local.sin_family=AF_INET;local.sin_port=htons(port);//主机转网络local.sin_addr.s_addr=INADDR_ANY;//随机绑定服务器ipif(bind(listen_sock,(struct sockaddr*)&local,sizeof(local))<0){std::cerr<<"绑定失败"<<std::endl;exit(-2);}//建立链接
#define BACK_LOG 5if(listen(listen_sock,BACK_LOG)<0){std::cerr<<"链接失败"<<std::endl;exit(-3);}}//获取链接void Loop(){//获取客户端信息struct sockaddr_in client;//signal(SIGCHID,hander);//hander是信号捕捉方法while(true){socklen_t len=sizeof(client);//获取新链接int sock=accept(listen_sock,(struct sockaddr*)&client,&len);if(sock<0){std::cerr<<"接受链接失败"<<std::endl;continue;//继续接受其他链接请求}//多进程处理多个客户端pid_t id=fork();if(id==0)//子进程{//子进程,与子进程的子进程不关心listen_sockclose(listen_sock);if(fork()>0){exit(0);//子进程直接退出后子进程的子进程变为孤儿进程被守护进程接管,不用等待了}//子进程的子进程,处理业务std::cout<<"获取新连接成功! ip["<<inet_ntoa(client.sin_addr)<<"] port["<<ntohs(client.sin_port)<<"]"<<std::endl;//整数ip转为字符ip形式,网络字节端口转化为本地端口//开始服务std::string CIp=inet_ntoa(client.sin_addr);int CPort=ntohs(client.sin_port);Sever(sock,CIp,CPort);exit(0);}//不能使用阻塞等待,可以使用信号机制忽略SIGCHID信号,或者使用两次fork函数close(sock);//父进程不关心客户端的链接请求,请求交给子进程做。waitpid(id,nullptr,0);//不会阻塞,因为id进程创建完子进程会立即退出,所以不会阻塞。}}void Sever(int sock,std::string&ip,int port){char buff[1024];while(true){memset(buff,0,sizeof(buff));ssize_t ReadSize=read(sock,buff,sizeof(buff)-1);if(ReadSize>0){buff[ReadSize]='\0';//添加字符串结束标志std::cout<<"Client["<<ip<<"-port-"<<port<<"]# "<<buff<<std::endl;write(sock,buff,ReadSize);//向客户端写入数据}else if(ReadSize==0){//对端关闭链接std::cout<<"Client["<<ip<<"-port-"<<port<<"]# 关闭"<<std::endl;break;}else{std::cerr<<sock<<"读取错误"<<std::endl;break;}}std::cout<<"服务终止"<<std::endl;}~TcpSever(){if(listen_sock>=0){close(listen_sock);}}
};
启动服务端
#include"Tcp_Sever.h"// Tcp_Sever +portvoid User(char*name)
{std::cout<<name<<" + port"<<std::endl;
}int main(int argc,char*argv[])
{if(argc!=2){User(argv[0]);exit(-1);}TcpSever*Sever=new TcpSever(atoi(argv[1]));//将字符串形式的端口号转化为整数形式Sever->InitSever();Sever->Loop();return 0;
}
客户端
#pragma once#include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string>
#include<string.h>class TcpClient
{private:std::string sev_ip;//服务器ipint sev_port;int sock;public:TcpClient(std::string _ip,int _sev_port):sev_ip(_ip),sev_port(_sev_port),sock(-1){}void InitClient(){sock=socket(AF_INET,SOCK_STREAM,0);if(sock<0){std::cerr<<"创建套接字失败"<<std::endl;exit(-1);}//客户端不需要绑定监听}//启动客户端void Start(){//向服务器发送链接//填充服务器信息struct sockaddr_in sever;memset(&sever,0,sizeof(sever));sever.sin_family=AF_INET;sever.sin_port=htons(sev_port);//服务器开放的端口sever.sin_addr.s_addr=inet_addr(sev_ip.c_str());//服务器的ip地址if(connect(sock,(struct sockaddr*)&sever,sizeof(sever))==0){//与服务器交互std::cout<<"发送交互请求成功"<<std::endl;Request(sock);}else{std::cerr<<"交互失败"<<std::endl;}}void Request(int Sock){std::string meg;while(true){std::cout<<"输入信息#";std::cin>>meg;char buff[1024];write(Sock,meg.c_str(),meg.size());//读取服务器发送的消息ssize_t ReadSize=read(sock,buff,sizeof(buff)-1);if(ReadSize>0){buff[ReadSize]='\0';}std::cout<<"Sever#"<<buff<<std::endl;}}~TcpClient(){if(sock>=0){close(sock);}}
};
启动客户端
#include"Tcp_Client.h"// ./Tcp_Client +ip +portvoid User(char*name)
{std::cout<<name<<" + sever_ip + sever_port"<<std::endl;
}int main(int argc,char*argv[])
{if(argc!=3){User(argv[0]);exit(-1);}TcpClient*Client=new TcpClient(argv[1],atoi(argv[2]));Client->InitClient();Client->Start();return 0;
}
2.多线程版本
注意:在类内部的成员函数,调用类内非静态成员函数时会自动带this指针。而线程执行的函数要求void* Hander(void*)类型,所以线程执行函数要用static修饰。
服务端
#pragma once #include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#include<fcntl.h>
#include<signal.h>
#include<sys/wait.h>
#include<pthread.h>#define DEF_PORT 8081//通信结构体
class Pragram{public:int sock;std::string ip;int port;Pragram(int _sock,std::string _ip,int _port):sock(_sock),ip(_ip),port(_port){}
};class TcpSever
{private:int port;int listen_sock;//监听套接字public: TcpSever(int _port=DEF_PORT):port(_port),listen_sock(-1){}void InitSever(){listen_sock=socket(AF_INET,SOCK_STREAM,0);//IPV4流式套接if(listen_sock<0){std::cerr<<"监听套接字创建失败"<<std::endl;exit(-1);}//绑定struct sockaddr_in local;memset(&local,'\0',sizeof(local));//初始化结构体local.sin_family=AF_INET;local.sin_port=htons(port);//主机转网络local.sin_addr.s_addr=INADDR_ANY;//随机绑定服务器ipif(bind(listen_sock,(struct sockaddr*)&local,sizeof(local))<0){std::cerr<<"绑定失败"<<std::endl;exit(-2);}//建立链接
#define BACK_LOG 5if(listen(listen_sock,BACK_LOG)<0){std::cerr<<"链接失败"<<std::endl;exit(-3);}std::cout<<"服务启动成功"<<std::endl;}//获取链接void Loop(){//获取客户端信息struct sockaddr_in client;//signal(SIGCHID,hander);//hander是信号捕捉方法while(true){socklen_t len=sizeof(client);//获取新链接int sock=accept(listen_sock,(struct sockaddr*)&client,&len);if(sock<0){std::cerr<<"接受链接失败"<<std::endl;continue;//继续接受其他链接请求}pthread_t tid;std::string ip=inet_ntoa(client.sin_addr);int port=ntohs(client.sin_port);Pragram*msg=new Pragram(sock,ip,port);pthread_create(&tid,nullptr,HanderQuest,msg);}}private:static void* HanderQuest(void*arg){Pragram*msg=(Pragram*)arg;pthread_detach(pthread_self());//线程分离std::cout<<"获取新连接成功"<<"[ ip:"<<msg->ip<<" port:"<<msg->port<<" ]"<<std::endl;Sever(msg->sock,msg->ip,msg->port);close(msg->sock);delete msg;return nullptr;}static void Sever(int sock,std::string&ip,int port){char buff[1024];while(true){memset(buff,0,sizeof(buff));ssize_t ReadSize=read(sock,buff,sizeof(buff)-1);if(ReadSize>0){buff[ReadSize]='\0';//添加字符串结束标志std::cout<<"Client["<<ip<<"-port-"<<port<<"]# "<<buff<<std::endl;write(sock,buff,ReadSize);//向客户端写入数据}else if(ReadSize==0){//对端关闭链接std::cout<<"Client["<<ip<<"-port-"<<port<<"]# 关闭"<<std::endl;break;}else{std::cerr<<sock<<"读取错误"<<std::endl;break;}}std::cout<<"服务终止"<<std::endl;}~TcpSever(){if(listen_sock>=0){close(listen_sock);}}
};
客户端代码部分不变。
3.模板线程池版本
线程池代码:
PthreadPool.h
#pragma once #include<iostream>
#include<pthread.h>
#include<queue>#define NUM 5template<typename Task>
class ThreadPool
{private:std::queue<Task> _task_queue;//临界资源pthread_mutex_t _lock;int _thread_num;pthread_cond_t _cond;public:ThreadPool(int Num=NUM):_thread_num(Num){pthread_mutex_init(&_lock,nullptr);pthread_cond_init(&_cond,nullptr);}bool IsEmpty(){return _task_queue.empty();}static void*Routine(void*arg)//静态函数无隐含的this指针{pthread_detach(pthread_self());ThreadPool<Task>*self=(ThreadPool<Task>*)arg;while(true){pthread_mutex_lock(&(self->_lock));while(self->IsEmpty())//循环检测临界资源是否就绪{//休眠pthread_cond_wait(&(self->_cond),&(self->_lock));}//任务队列有任务Task t;self->Pop(t);pthread_mutex_unlock(&(self->_lock));//解锁后处理任务t.Run();}}void Push(const Task&in)//外部添加任务{pthread_mutex_lock(&_lock);_task_queue.push(in);//唤醒一个线程pthread_cond_signal(&_cond);pthread_mutex_unlock(&_lock);}void Pop(Task&out)//线程获取任务{out=_task_queue.front();_task_queue.pop();}~ThreadPool(){pthread_mutex_destroy(&_lock);pthread_cond_destroy(&_cond);}void InitThreadPool(){pthread_t tid;for(int i=0;i<_thread_num;i++){//为了避免传参时C++传this指针,在线程执行方法上带static。//传参数时将this指针传到线程执行方法上。 pthread_create(&tid,nullptr,Routine,this);}}
};
设计任务Task.h
#pragma once #include<iostream>
#include<string>
#include<unistd.h>
#include<string.h>struct Hander{void operator()(int sock,std::string&ip,int port){char buff[1024];while(true){memset(buff,0,sizeof(buff));ssize_t ReadSize=read(sock,buff,sizeof(buff)-1);if(ReadSize>0){buff[ReadSize]='\0';//添加字符串结束标志std::cout<<"Client["<<ip<<"-port-"<<port<<"]# "<<buff<<std::endl;write(sock,buff,ReadSize);//向客户端写入数据}else if(ReadSize==0){//对端关闭链接std::cout<<"Client["<<ip<<"-port-"<<port<<"]# 关闭"<<std::endl;break;}else{std::cerr<<sock<<"读取错误"<<std::endl;break;}}std::cout<<"服务终止"<<std::endl;close(sock);}
};class Task{private:int sock;std::string ip;int port;Hander condut;//仿函数public:Task()=default;Task(int _sock,std::string _ip,int _port):sock(_sock),ip(_ip),port(_port){}void Run(){condut(sock,ip,port);}};
服务端代码
#pragma once #include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#include<fcntl.h>
#include<signal.h>
#include<sys/wait.h>
#include<pthread.h>#include"ThreadPool.h"
#include"Task.h"#define DEF_PORT 8081//通信结构体
class Pragram{public:int sock;std::string ip;int port;Pragram(int _sock,std::string _ip,int _port):sock(_sock),ip(_ip),port(_port){}
};class TcpSever
{private:int port;int listen_sock;//监听套接字ThreadPool<Task>*Pool;public: TcpSever(int _port=DEF_PORT):port(_port),listen_sock(-1),Pool(nullptr){}void InitSever(){listen_sock=socket(AF_INET,SOCK_STREAM,0);//IPV4流式套接if(listen_sock<0){std::cerr<<"监听套接字创建失败"<<std::endl;exit(-1);}//绑定struct sockaddr_in local;memset(&local,'\0',sizeof(local));//初始化结构体local.sin_family=AF_INET;local.sin_port=htons(port);//主机转网络local.sin_addr.s_addr=INADDR_ANY;//随机绑定服务器ipif(bind(listen_sock,(struct sockaddr*)&local,sizeof(local))<0){std::cerr<<"绑定失败"<<std::endl;exit(-2);}//建立链接
#define BACK_LOG 5if(listen(listen_sock,BACK_LOG)<0){std::cerr<<"链接失败"<<std::endl;exit(-3);}std::cout<<"服务启动成功"<<std::endl;Pool=new ThreadPool<Task>(10);//10个线程}//获取链接void Loop(){Pool->InitThreadPool();//获取客户端信息struct sockaddr_in client;//signal(SIGCHID,hander);//hander是信号捕捉方法while(true){socklen_t len=sizeof(client);//获取新链接int sock=accept(listen_sock,(struct sockaddr*)&client,&len);if(sock<0){std::cerr<<"接受链接失败"<<std::endl;continue;//继续接受其他链接请求}std::string ip=inet_ntoa(client.sin_addr);int port=ntohs(client.sin_port);Task asig(sock,ip,port);Pool->Push(asig);}}~TcpSever(){if(listen_sock>=0){close(listen_sock);}}
};
客户端代码不需要改变
相关文章:
Linux网络:网络套接字-TCP回显服务器——多进程/线程池(生产者消费者模型)
1.多进程版本 这里选择创建子进程,让子进程再创建子进程。父进程等待子进程,子进程的子进程处理业务逻辑。因为子进程是直接退出,子进程的子进程变成孤儿进程被系统管理,所以父进程在等待的时候不是阻塞等待的,所以可…...
Redis 篇-深入了解基于 Redis 实现消息队列(比较基于 List 实现消息队列、基于 PubSub 发布订阅模型之间的区别)
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 消息队列的认识 2.0 基于 List 实现消息队列 2.1 基于 List 实现消息队列的优缺点 3.0 基于 PubSub 实现消息队列 3.1 基于 PubSub 的消息队列优缺点 4.0 基于 St…...
python 学习一张图
python学习一张图,python的特点的是学的快,一段时间不用,忘记的也快,弄一张图及一些入门案例吧。 写一个简单的测试: #!/usr/bin/python # -*- coding: UTF-8 -*- import osdef add_num(a, b):return a bif __name__…...
通过Docker部署 MongoDB 服务器
今天我们将在三丰云的免费服务器上进行 MongoDB 的部署测试。这款不错的免费服务器提供了很好的性能,1核CPU、1G内存、10G硬盘和5M带宽,足以满足我们的基本需求。三丰云的服务稳定,操作简单,真是一个值得推荐的选择,特…...
无人机避障雷达技术详解
随着无人机技术的飞速发展,其应用领域已经从最初的军事领域扩展到商业、农业、建筑巡检、应急救援、物流运输等多个领域。在这些多样化的应用场景中,无人机的安全性和稳定性显得尤为重要。无人机避障技术作为保障无人机安全飞行的核心技术之一࿰…...
2009-2023年上市公司华证esg评级评分数据(年度+季度)(含细分项)
2009-2023年上市公司华证esg评级评分数据(年度季度)(含细分项) 1、时间:2009-2023年 2、来源:整理自wind 3、指标:证券代码、年份、证券简称、评级日期、综合评级、综合得分、E评级、E得分、…...
C++ 模板进阶知识——stdenable_if
目录 C 模板进阶知识——std::enable_if1. 简介和背景基本语法使用场景 2. std::enable_if 的基本用法示例:限制函数模板只接受整数类型 3. SFINAE 和 std::enable_if示例:使用 SFINAE 进行函数重载SFINAE 的优点应用场景 4. 在类模板中使用 std::enable…...
国内外ChatGPT网站集合,无限制使用【2024-09最新】~
经过我一年多以来,使用各种AI工具的体验,我收集了一批AI工具和站点 这些工具都是使用的最强最主流的模型,也都在各个领域里都独领风骚的产品。 而且,这些工具你都可以无限制地使用。 无论你是打工人、科研工作者、学生、文案写…...
如何在VUE3中使用函数式组件
在Vue 3中,函数式组件的概念与Vue 2相似,但实现方式有所不同。函数式组件是一种无状态、无实例的组件,它们只根据传入的props和context来渲染输出。在Vue 3中,你可以通过定义一个函数并返回一个渲染函数来使用函数式组件。但是&am…...
linux访问外网的设置
Ubuntu | LUCKFOX WIKI 开发板配置 添加路由信息 sudo route add default gw 172.32.0.100添加 DNS servers 打开文件 sudo vi /etc/resolv.conf添加以下内容: nameserver 8.8.8.8联网测试 ping www.baidu.com开机自动配置 路由信息和 DNS servers 重启后会被清除,我们创建…...
PHP轻松创建高效收集问卷调查小程序系统源码
轻松创建,高效收集 —— 问卷调查小程序,你的调研神器! 一、告别繁琐,一键开启调研之旅 还在为设计问卷、收集数据而头疼不已吗?现在,有了“问卷调查小程序”,一切都变得轻松简单!无…...
Redis面试必问:Redis为什么快?Redis五大基本数据类型
请记住胡广一句话,所有的中间件所有的框架都是建立在基础之上,数据结构,计算机网络,计算机原理大伙一定得看透!!~ 1. Redis快的秘密 相信大部分Redis初学者都会忽略掉一个重要的知识点,Redis…...
InternVL2- dockerfile环境变量持久化使用`ENV`而不是`RUN export`来设置环境变量,以确保环境变量在容器运行时仍然可用
在Dockerfile中使用RUN export命令设置环境变量并不是一种持久化的方式。当你在Dockerfile中使用export命令时,它只会在当前构建阶段生效,并不会被持久化到生成的镜像中。这是因为export命令实际上是在shell环境中设置环境变量,而Docker构建过…...
Python(PyTorch和TensorFlow)图像分割卷积网络导图(生物医学)
🎯要点 语义分割图像三层分割椭圆图像脑肿瘤图像分割动物图像分割皮肤病变分割多模态医学图像多尺度特征生物医学肖像多类和医学分割通用图像分割模板腹部胰腺图像分割分类注意力网络病灶边界分割气胸图像分割 Python生物医学图像卷积网络 该网络由收缩路径和扩…...
DevOps实现CI/CD实战(七)- Jenkins集成k8s实现自动化CI
自动化CI操作 1. 安装gitlab plugin 工具 ##### 2. 配置流水线任务的构建触发器,复制URL:http://192.168.201.111:8080/project/pipeline 3. Gitlab配置Webhooks,将上面的url:http://192.168.201.111:8080/project/pipeline粘…...
从ES6到ES2023 带你深入了解什么是ES
从ES6到ES2023,我们深入探索ECMAScript(简称ES)的演变与发展,了解这一JavaScript标准背后的技术革新和进步。ECMAScript作为JavaScript的标准化版本,每年都在不断推出新版本,为开发者带来更加丰富和强大的功…...
openVX加速-常见问题:适用场景、AI加速、安装方式等
1. 哪些算法处理推荐使用 OpenVX OpenVX 是非常适合图像处理和计算机视觉任务的框架,特别是在需要高性能和硬件加速的场景下。如果你的前处理和后处理涉及到图像滤波、边缘检测、颜色转换等操作,使用 OpenVX 可以带来性能提升。 OpenVX 更适合处理以下…...
国产芯片LT8711HE:TYPE-C/DP1.2转HDMI2.0转换器,4k60Hz高分辨率
以下为LT8711HE芯片的简单介绍,如有介绍不尽之处,请指出 LT8711HE是一个高性能的Type-C/DP1.2到HDMI2.0转换器,用于连接USB Type-C源或DP1.2源到HDMI2.0接收器。 LT8711HE集成了一个DP1.2兼容的接收器和一个HDMI2.0兼容的发射器。另外&…...
论文翻译:arxiv-2024 Benchmark Data Contamination of Large Language Models: A Survey
Benchmark Data Contamination of Large Language Models: A Survey https://arxiv.org/abs/2406.04244 大规模语言模型的基准数据污染:一项综述 文章目录 大规模语言模型的基准数据污染:一项综述摘要1 引言 摘要 大规模语言模型(LLMs&…...
Java+Swing用户信息管理系统
JavaSwing用户信息管理系统 一、系统介绍二、功能展示1.管理员登陆2.用户信息查询3.用户信息添加4.用户信息修改5.用户信息删除 三、系统实现1.UserDao .java 四、其它1.其他系统实现 一、系统介绍 该系统实现了管理员系统登陆、用户信息查询、用户信息添加、用户信息修改、用…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...
多元隐函数 偏导公式
我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式,给定一个隐函数关系: F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 🧠 目标: 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z、 …...
