当前位置: 首页 > news >正文

如何创建基于udp的客户端和服务端

1.先创建好udpServer.hpp、udpServer.cc、udpClient.hpp、udpClient.cc的框架。

#pragma once
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <functional>
#include"userManager"
#include<pthread.h>
using namespace std;
const static string defaultip = "0.0.0.0";
// typedef function<void(int,string,uint16_t,string)> func_t;
typedef void (*func_t)(int,string,uint16_t,string);
class udpServer
{
public:udpServer(uint16_t port,func_t callback) : _port(port),_callback(callback){}void init(){}void start(){}~udpServer() {}private:int _fd;uint16_t _port;string _ip;func_t _callback;
};
#include "udpServer.hpp"
#include <memory>
#include<fstream>
using namespace std;
int main(int argc, char *argv[])
{if (argc != 2){cout << "输入错误,请重新输入" << endl;}uint16_t port = atoi(argv[1]);unique_ptr<udpServer> server(new udpServer(port, callback));server->init();server->start();return 0;
}
#pragma once
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <pthread.h>
using namespace std;
class udpClient
{public:udpClient(string serverip,uint16_t serverport):_serverip(serverip),_serverport(serverport),_fd(-1){}void init(){}void start(){}~udpClient(){}private:int _fd;string _serverip;uint16_t _serverport;pthread_t reader;//这是后期需要的,看不懂接着往下看就可以
};
#include"udpClient.hpp"
#include<memory>
using namespace std;int main(int argc,char* argv[]){if(argc!=3){cout<<"输入错误,请重新输入"<<endl;}uint16_t port = atoi(argv[2]);string ip = argv[1];unique_ptr<udpClient> client(new udpClient(ip,port));client->init();client->start();
}

2.init初始化。

 //udpServer.hpp
void init(){// 创建套接字返回fd_fd = socket(AF_INET, SOCK_DGRAM, 0);if (_fd == -1){cerr << "socket error:" << errno << ":" << strerror(errno) << endl;exit(1);}// 将fd和ip,port进行绑定struct sockaddr_in sock;sock.sin_family = AF_INET;sock.sin_port = htons(_port);sock.sin_addr.s_addr = INADDR_ANY;int n = bind(_fd, (struct sockaddr *)&sock, sizeof(sock));if (n == -1){cerr << "bind error:" << errno << ":" << strerror(errno) << endl;exit(2);}}
//udpClient.hpp 
void init(){_fd = socket(AF_INET,SOCK_DGRAM,0);if(_fd == -1){cout<<"socket err:"<<errno<<":"<<strerror(errno)<<endl;exit(1);}}

3.start发送、接收数据。

 //udpServer.cc
void callback(int fd, string ip, uint16_t port, string messages)
{sockaddr_in client;socklen_t len = sizeof(client);client.sin_family = AF_INET;client.sin_port = htons(port);client.sin_addr.s_addr = inet_addr(ip.c_str());messages = "服务端的输出结果:"+messages;sendto(fd, messages.c_str(), messages.size(), 0,(struct sockaddr *)&client, len);}//udpServer.hpp
void start(){char buffer[1024];size_t len = sizeof(buffer);char writer[1024];struct sockaddr_in clientsock;socklen_t clientlen = sizeof(clientsock);while (1)//服务器的本质就是一个死循环{size_t n = recvfrom(_fd, buffer, len-1, 0, (struct sockaddr *)&clientsock, &clientlen);if (n > 0){buffer[n]=0;string ip = inet_ntoa(clientsock.sin_addr); // uint32_t->stringuint16_t port = ntohs(clientsock.sin_port);string messages = buffer;cout << ip << "[" << port << "]" << "#" << messages << endl;_callback(_fd,ip,port,messages);}}}
 //udpCLient.hpp
static void* readroutine(void* args){pthread_detach(pthread_self());udpClient* c = static_cast<udpClient*>(args);sockaddr_in server;socklen_t serverlen = sizeof(server);while(1){char buffer[1024];int len = sizeof(buffer);size_t n = recvfrom(c->_fd, buffer, len-1, 0, (struct sockaddr *)&server, &serverlen);if (n > 0){buffer[n]=0;cout <<buffer << endl;}}}void start(){pthread_create(&reader,NULL,readroutine,(void*)this);char buffer[1024];struct sockaddr_in serveraddr;serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(_serverport);serveraddr.sin_addr.s_addr = inet_addr(_serverip.c_str());while(1){cin>>buffer;ssize_t n = sendto(_fd,buffer,sizeof(buffer),0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));if(n == -1){cout<<"sendto err:"<<errno<<":"<<strerror(errno)<<endl;}}}

完整代码:

udpClient.cc

#include"udpClient.hpp"
#include<memory>
using namespace std;int main(int argc,char* argv[]){if(argc!=3){cout<<"输入错误,请重新输入"<<endl;}uint16_t port = atoi(argv[2]);string ip = argv[1];unique_ptr<udpClient> client(new udpClient(ip,port));client->init();client->start();
}

 udpClient.hpp

#pragma once
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <pthread.h>
using namespace std;
class udpClient
{public:udpClient(string serverip,uint16_t serverport):_serverip(serverip),_serverport(serverport),_fd(-1){}void init(){_fd = socket(AF_INET,SOCK_DGRAM,0);if(_fd == -1){cout<<"socket err:"<<errno<<":"<<strerror(errno)<<endl;exit(1);}}static void* readroutine(void* args){pthread_detach(pthread_self());udpClient* c = static_cast<udpClient*>(args);sockaddr_in server;socklen_t serverlen = sizeof(server);while(1){char buffer[1024];int len = sizeof(buffer);size_t n = recvfrom(c->_fd, buffer, len-1, 0, (struct sockaddr *)&server, &serverlen);if (n > 0){buffer[n]=0;cout <<buffer << endl;}}}void start(){pthread_create(&reader,NULL,readroutine,(void*)this);char buffer[1024];struct sockaddr_in serveraddr;serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(_serverport);serveraddr.sin_addr.s_addr = inet_addr(_serverip.c_str());while(1){cin>>buffer;ssize_t n = sendto(_fd,buffer,sizeof(buffer),0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));if(n == -1){cout<<"sendto err:"<<errno<<":"<<strerror(errno)<<endl;}}}~udpClient(){}private:int _fd;string _serverip;uint16_t _serverport;pthread_t reader;
};

 udpServer.cc

#include "udpServer.hpp"
#include <memory>
#include<fstream>
using namespace std;
// 处理方式1:翻译软件
unordered_map<string, string> dictmap;
void to_map(string messages);
// 1.打开文件,按行读取
void openfile()
{ifstream in;in.open("dict.txt",std::ios::binary);if(in.is_open()){std::string line;while(getline(in,line)){to_map(line);}}
}
// 2.按行存到map中
void to_map(string messages)
{size_t pos = messages.find(":");dictmap.insert(make_pair(messages.substr(0, pos), messages.substr(pos + 1)));
}
// 3.接收传来的message并通过map查询
void translate(int fd, string ip, uint16_t port, string messages)
{sockaddr_in client;socklen_t len = sizeof(client);client.sin_family = AF_INET;client.sin_port = htons(port);client.sin_addr.s_addr = inet_addr(ip.c_str());if (dictmap.find(messages) != dictmap.end()){cout<<"messages:"<<dictmap[messages].c_str()<<endl;sendto(fd, dictmap[messages].c_str(), dictmap[messages].size(), 0,(struct sockaddr *)&client, len);}else{string mes = "无结果";sendto(fd, mes.c_str(), mes.size(),0, (struct sockaddr *)&client, len);}
}
// 4.test测试文件有没有加载成功
void printdict()
{for (auto e : dictmap){cout << e.first << ":" << e.second << endl;}
}
// 处理方式2:群聊
onlineUser onlineuser;
void group_chat(int fd, string ip, uint16_t port, string messages)
{// 将客户端的信息传进来onlineuser.addOnlineUser(ip, port);onlineuser.broadcastMessage(fd, ip, port, messages);
}
// 处理方式3:最简单版本收到什么原样返回
void callback(int fd, string ip, uint16_t port, string messages)
{sockaddr_in client;socklen_t len = sizeof(client);client.sin_family = AF_INET;client.sin_port = htons(port);client.sin_addr.s_addr = inet_addr(ip.c_str());messages = "服务端的输出结果:"+messages;sendto(fd, messages.c_str(), messages.size(), 0,(struct sockaddr *)&client, len);}
int main(int argc, char *argv[])
{if (argc != 2){cout << "输入错误,请重新输入" << endl;}uint16_t port = atoi(argv[1]);//openfile();//printdict();unique_ptr<udpServer> server(new udpServer(port, callback));server->init();server->start();return 0;
}

 udpServer.hpp

#pragma once
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <functional>
#include"userManager"
#include<pthread.h>
using namespace std;const static string defaultip = "0.0.0.0";
// typedef function<void(int,string,uint16_t,string)> func_t;
typedef void (*func_t)(int,string,uint16_t,string);
class udpServer
{
public:udpServer(uint16_t port,func_t callback) : _port(port),_callback(callback){}void init(){// 创建套接字返回fd_fd = socket(AF_INET, SOCK_DGRAM, 0);if (_fd == -1){cerr << "socket error:" << errno << ":" << strerror(errno) << endl;exit(1);}// 将fd和ip,port进行绑定struct sockaddr_in sock;sock.sin_family = AF_INET;sock.sin_port = htons(_port);sock.sin_addr.s_addr = INADDR_ANY;int n = bind(_fd, (struct sockaddr *)&sock, sizeof(sock));if (n == -1){cerr << "bind error:" << errno << ":" << strerror(errno) << endl;exit(2);}}void start(){char buffer[1024];size_t len = sizeof(buffer);char writer[1024];struct sockaddr_in clientsock;socklen_t clientlen = sizeof(clientsock);while (1){size_t n = recvfrom(_fd, buffer, len-1, 0, (struct sockaddr *)&clientsock, &clientlen);if (n > 0){buffer[n]=0;string ip = inet_ntoa(clientsock.sin_addr); // uint32_t->stringuint16_t port = ntohs(clientsock.sin_port);string messages = buffer;cout << ip << "[" << port << "]" << "#" << messages << endl;_callback(_fd,ip,port,messages);}}}~udpServer() {}private:int _fd;uint16_t _port;string _ip;pthread_t writer;func_t _callback;
};

 makefile

cc=g++
.PHONY:all
all:udpClient udpServerudpClient:udpClient.cc$(cc) -o $@ $^ -std=c++11 -lpthread
udpServer:udpServer.cc$(cc) -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:rm -f udpClient udpServer

以下是拓展的代码:

群聊:userManager

#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <functional>
using namespace std;
class User
{
public:User(std::string ip, uint16_t port) : _ip(ip), _port(port){}~User(){}std::string _ip;int16_t _port;
};
class onlineUser
{
public:onlineUser() {}~onlineUser() {}void addOnlineUser(std::string ip, uint16_t port){string id = ip + "[" + std::to_string(port) + "]#";onUser.insert(make_pair(id, User(ip, port)));}void offOnlineUser(std::string ip, uint16_t port){string id = ip + "[" + std::to_string(port) + "]#";onUser.erase(id);}void broadcastMessage(int sockfd, const string &ip, const int16_t &port, const string &messages){string id = ip + "[" + std::to_string(port) + "]#";for (auto &user : onUser){if (user.first != id){sockaddr_in usersock;usersock.sin_family = AF_INET;usersock.sin_port = htons(user.second._port);usersock.sin_addr.s_addr = inet_addr(user.second._ip.c_str());string sendmessage = id + messages;sendto(sockfd, sendmessage.c_str(), sendmessage.size(), 0, (struct sockaddr *)&usersock, sizeof(usersock));}}}private:unordered_map<string, User> onUser;
};

 字典:dict.txt

hello:你好
why:为什么
so:所以
then:然后

相关文章:

如何创建基于udp的客户端和服务端

1.先创建好udpServer.hpp、udpServer.cc、udpClient.hpp、udpClient.cc的框架。 #pragma once #include <string> #include <iostream> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <cerrno> #include…...

ThinkPHP框架审计--基础

基础入门 搭建好thinkphp 查看版本方法&#xff0c;全局搜version 根据开发手册可以大致了解该框架的路由 例如访问url http://127.0.0.1:8094/index.php/index/index/index 对应代码位置 例如在代码下面添加新方法 那么访问这个方法的url就是 http://127.0.0.1:8094/index.…...

Java8 CompletableFuture异步编程

文章目录 CompletableFuturede介绍CompletableFuturede使用场景常用异步编程实现方案- Thread- ExecutorService- CountDownLatch- CyclicBarrier- ForkJoinPool- CompletableFuture各种实现方案总结 CompletableFuturede结构结构梳理- Future接口- CompletionStage接口常用方法…...

Java的Mvc整合Swagger的knife4框架

Swagger的介绍 Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。使用Swagger&#xff0c;就是把相关的信息存储在它定义的描述文件里面&#xff08;yml或json格式&#xff09;&#xff0c;再通过维护这个描述 文件可以去更…...

分阶段构建在复杂系统中的应用:以推荐系统为例

引言 在信息技术飞速发展的今天&#xff0c;复杂系统的构建已经成为许多企业和组织面临的重要挑战。复杂系统通常由多个相互依赖、相互作用的组件构成&#xff0c;这些组件在功能上相互关联&#xff0c;形成了一个高度耦合的整体。对于这样的系统&#xff0c;采用分阶段构建的…...

2024年12月9日历史上的今天大事件早读

1447年12月9日 中国明朝皇帝明宪宗出生 1824年12月9日 西属美洲独立战争的阿亚库乔之战爆发 1882年12月9日 中国清代数学家李善兰逝世 1917年12月9日 葡萄牙共和政府垮台 1935年12月9日 红军表示与东北抗联军一致抗日 1935年12月9日 “一二九”运动爆发 1941年12月9日 中…...

快捷构建AI大模型,源码自取可直接运行

Node.js 和 WebSocket 实现一个基于kimi&#xff08;Moonshot 月之暗大模型&#xff09;的AI工具 前端&#xff1a;前端界面比较容易&#xff0c;只需要简单的额css js即可&#xff0c;本文使用vue作为作为demo。 后端&#xff1a;我java很垃圾&#xff0c;写不出好的代码&am…...

怎么为开源项目做贡献提PR?

GitHub 慢的话&#xff0c;https://ask.csdn.net/questions/8166374 复刻项目 以 https://github.com/open-frame/uniapp-init 项目为例 复刻完就会在你的仓库里有个同样的项目 拉取复刻下来的项目 然后常规的改动项目、git推送。比如我改了一个忽略文件&#xff1a; 提交…...

如何在 JavaScript 中设置定时器?

在 JavaScript 中&#xff0c;设置定时器通常使用两个内置的函数&#xff1a;setTimeout() 和 setInterval()。它们允许你在指定的时间延迟后执行某个函数或者以某个间隔反复执行某个函数。下面&#xff0c;我将结合实际项目代码示例讲解如何使用它们。 1. setTimeout() — 延…...

【学习路线】Java

Java基础 基础 基础语法 面向对象 集合框架 JCF 进阶 并发编程 JVM 企业级开发 框架 Spring Boot Spring Cloud 分布式 高性能 高可用 安全 基建 Docker 实战 数据库 MySQL Redis 计算机基础 计算机组成原理 操作系统 计算机网络 数据结构与算法 设计模式 参考&#xff1a;…...

[GYCTF2020]Easyphp

[GYCTF2020]Easyphp 知识点 反序列化 、字符逃逸 解题 审代码 <?php error_reporting(0); session_start(); function safe($parm){$array array(union,regexp,load,into,flag,file,insert,"",\\,"*","alter");return str_replace($arr…...

JavaScript 数组的高级用法与最佳实践

在前端开发中&#xff0c;JavaScript 数组是不可或缺的工具。它们不仅用于存储数据&#xff0c;还提供了丰富的方法来操作和处理这些数据。掌握 JavaScript 数组的高级用法和最佳实践对于编写高效、可维护的代码至关重要。本文将深入探讨 JavaScript 数组的高级用法&#xff0c…...

通信协议 http、tcp、udp

目录 1. 五层网络协议 2. http 3. tcp、udp 4. tcp 3次握手、4次挥手 5. socket 6. httpclient 遇到的问题 1. Q: 使用 EntityUtils.toString(responseEntity, "UTF-8") 中文乱码 2. Q: org.apache.http.NoHttpResponseException: 221.6.16.203:8890 failed …...

Scala的隐式对象和隐式类

1.隐式对象 object Test1 {case class DatabaseConfig(drive:String,url:String)//隐式对象//格式:就是在对象前面加一个 implicit//作用:给函数当默认值implicit object MySqlConfig extends DatabaseConfig("sqlserver.jdbc","localhost:3306")//定义一…...

【AIGC】2016-ACCV-即时追捕:自然环境下的自动唇音同步

2016-ACCV-Out of time: automated lip sync in the wild 摘要1. 引言1.1 相关作品 2. 表示和架构2.1 音频流2.2 视觉流2.3 损失函数2.4 训练 3. 数据集3.1 编制训练数据 4. 实验4.1 确定口型同步误差4.2 应用&#xff1a;主动说话人检测4.3 应用&#xff1a;唇读 5. 结论参考文…...

启智畅想集装箱箱号识别算法,2台相机即可实现较高识别率

启智畅想集装箱箱号识别算法&#xff0c;在货车通道中使用时&#xff0c;一般配备2台相机即可。启智畅想集装箱箱号识别算法&#xff0c;在货车通道中使用时&#xff0c;一般配备2台相机即可实现对集装箱箱号的精准捕捉与识别。这两台相机分别安装在货车通道的后侧和随意侧面&a…...

让IIS支持PUT请求解决IIS里不支持PUT请求的问题405 Method Not Allowed

文章目录 一、问题描述二、解决方案1.删除WebDav模块2.修改Web.config&#xff08;可选&#xff09; 一、问题描述 好不容易系统开发好了&#xff0c;兴高采烈地上线&#xff0c;部署好了网站&#xff0c;访问正常&#xff0c;打开方式正确&#xff01; 但当我修改某些数据时&…...

入门级捡垃圾工作站记录

入门级捡垃圾工作站记录 想法 一直想着拥有有一台自己的多功能机子&#xff0c;一个笔记本很难事事包办&#xff0c;本来打算配一个台式机&#xff0c;后来研究了一下&#xff0c;索性捡垃圾拼装的工作站&#xff0c;性价比更高&#xff0c;稳定性也更强&#xff0c;而且还可…...

2024.12.9——攻防世界ics-06

知识点&#xff1a;index文件 ics 文件&#xff08;iCalendar 格式文件&#xff09; bp抓包 密码爆破 题目&#xff1a;云平台报表中心收集了设备管理基础服务的数据&#xff0c;但是数据被删除了&#xff0c;只有一处留下了入侵者的痕迹。 一、解题思路 step 1 打开靶机审题…...

微信小程序介绍-以及写项目流程(重要)

前言&#xff1a;本篇文章介绍微信小程序以及项目介绍&#xff1a; 文章介绍&#xff1a;介绍了微信小程序常用的指令、组件、api。tips&#xff1a;最好按照官方文档来进行学习&#xff0c;大致可以我的目录来学习&#xff0c;对于写项目是没有问题的 微信小程序官方文档https…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

C++ 类基础:封装、继承、多态与多线程模板实现

前言 C 是一门强大的面向对象编程语言&#xff0c;而类&#xff08;Class&#xff09;作为其核心特性之一&#xff0c;是理解和使用 C 的关键。本文将深入探讨 C 类的基本特性&#xff0c;包括封装、继承和多态&#xff0c;同时讨论类中的权限控制&#xff0c;并展示如何使用类…...

背包问题双雄:01 背包与完全背包详解(Java 实现)

一、背包问题概述 背包问题是动态规划领域的经典问题&#xff0c;其核心在于如何在有限容量的背包中选择物品&#xff0c;使得总价值最大化。根据物品选择规则的不同&#xff0c;主要分为两类&#xff1a; 01 背包&#xff1a;每件物品最多选 1 次&#xff08;选或不选&#…...