网络编程套接字 | UDP套接字
前面的文章中我们叙述了网络编程套接字的一些预备知识点,从本文开始我们就将开始UDP套接字的编写。本文中的服务端与客户端都是在阿里云的云服务器进行编写与测试的。
udp_v1
在v1的版本中我们先来使用一下前面讲过得一些接口,简单的构建一个udp服务器:
// udp_server.cc
#include "udp_server.hpp"
#include <memory>using namespace std;
using namespace ns_server;
int main()
{unique_ptr<UdpServer> usvr(new UdpServer("1.1.1.1", 8082)); // 通过智能指针控制服务器的资源管理,并且向程序传入ip与端口号usvr->InitServer(); //服务器的初始化usvr->Start();return 0;
}
// udp_server.hpp
#pragma once#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
namespace ns_server
{// 用于展示返回对应的错误提示enum{SOCKET_ERR = 1,BIND_ERR};const static uint16_t default_port = 8080;class UdpServer{public:UdpServer(std::string ip, uint16_t port = default_port) : ip_(ip), port_(port){std::cout << "server addr: " << ip << " : " << port_ << std::endl;}void InitServer(){// 1. 创建socket接口,打开网络文件sock_ = socket(AF_INET, SOCK_DGRAM, 0);if (sock_ < 0){std::cerr << "create socket error: " << strerror(errno) << std::endl;exit(SOCKET_ERR);}std::cout << "create socket success: " << sock_ << std::endl; // 3// 2. 给服务器指明IP地址和端口号Portstruct sockaddr_in local; // 这个 local 在哪里定义呢?用户空间的特定函数的栈帧上,不在内核中! bzero(&local, sizeof(local)); // 清空上述字段udlocal.sin_family = AF_INET; // PF_INET 初始化socketaddr_in结构local.sin_port = htons(port_); // 本地主机序列构建的port_,需要从主机序列转变成网络序列// inet_addr: 1,2// 1. 字符串风格的IP地址,转换成为4字节int, "1.1.1.1" -> uint32_t -> 能不能强制类型转换呢?不能,这里要转化// 2. 需要将主机序列转化成为网络序列local.sin_addr.s_addr = inet_addr(ip_.c_str()); // sin_addr C++中的结构体在C++中可以进行转化,但是在C语言中不行// 这里需要将字符串转换uint32_t的类型,并且同时进行将主机序列转换成网络序列// inet_addr 函数将包含 IPv4 点十进制地址的字符串转换为IN_ADDR结构的正确地址。而在in_addr结构之中有in_addr_t s_addr的一个数据结构if (bind(sock_, (struct sockaddr*)&local, sizeof(local)) < 0) // 然后是绑定相关的套接字文件,此时需要就将前面在帧栈上定义的local进行绑定{std::cerr << "bind socket error: " << strerror(errno) << std::endl;exit(BIND_ERR);}std::cout << "bind socket success: " << sock_ << std::endl; //3}void Start() {}~UdpServer() {}private:int sock_;uint16_t port_;std::string ip_; // 后面需要去掉这个ip};
}
然后运行上述的程序会出现一个问题就是:
server addr: 1.1.1.1 : 8082
create socket success: 3
bind socket error: Cannot assign requested address
bind socket error: Cannot assign requested address 云服务器不需要bind ip地址,需要让服务器自己制定ip地址
云服务器,或者一款服务器,一般不要指明某一个确定的IP – 服务器可能有多张网卡,可能配有多个IP,我们要让我们的udpserver启动的时候bind本主机上的任意IP,然后我们对上述的v1版本进行修改。
// 需要修改的地方就是:
local.sin_addr.s_addr = INADDR_ANY; // 让我们的udpserver在启动的时候,bind本主机上的任意IP
server addr: 1.1.1.1 : 8082
create socket success: 3
bind socket success: 3
此时就可以正确的进行bind操作。
udp_v2
下面我们将上述的程序进行完善,添加上服务器正常工作的程序(我们想要完成的是客户端发送消息,服务端接收到消息并答应在终端上,同时将消息返回给客户端)
void Start()
{// 服务器的正常工作char buffer[1024];while (true){// 收// ssize_t 实际写入的大小 recvfrom(int sockfd 绑定的套接字, void *buf 接受数据存放的缓冲区, size_t len 缓冲区长度, int flags 读取方式(0), struct sockaddr *src_addr 需要知道client的IP和PORT 输入接收缓冲区, socklen_t *addrlen 实际结构体的大小); 输入输出型参数 需要知道谁发的数据struct sockaddr_in peer;socklen_t len = sizeof(peer); // 这里一定要写清楚,未来传入的缓冲区的大小int n = recvfrom(sock_, buffer, sizeof(buffer)-1/*因为这是以字符作为消息的类型,所以缓冲区预留一部分空间*/, 0, (struct sockaddr*)&peer, &len); // 消息的类型需要程序员来定义if (n > 0) buffer[n] = '\0';else continue;// 提取client信息std::string clientip = inet_ntoa(peer.sin_addr); // 把一个四字节的IP转化为字符串uint16_t clientport = ntohs(peer.sin_port); // 将从网络中获取的端口号转换成主机std::cout << clientip << "-" << clientport << "#" << buffer << std::endl;// 发sendto(sock_, buffer, strlen(buffer), 0, (struct sockaddr*)&peer, len); // 往文件中去写的时候,不需要携带\0}
}
然后对udp_server.cc文件进行修改,我们想要使用./udp_server port
的形式来运行程序,在运行程序的时候将端口号进行传入
static void usage(string proc)
{std::cout << "Usage:\n\t" << proc << " port\n" << std::endl;
}
// ./udp_server port
int main(int argc, char* argv[])
{if (argc != 2){usage(argv[0]);exit(USAGE_ERR);}uint16_t port = atoi(argv[1]); // 此处为char*类型的数据若是要传入port需要进行转换unique_ptr<UdpServer> usvr(new UdpServer(port));// bind socket error: Cannot assign requested address 云服务器不需要bind ip地址,需要让服务器自己制定ip地址// 自己本地装的虚拟机或者是物理机器是允许的,usvr->InitServer(); //服务器的初始化usvr->Start();return 0;
}
然后是服务端的代码
// udp_client.cc
#include <string>
#include <cstring>
// 127.0.0.1 本地回环,表示的就是当前的主机,通常用来进行本地通信或者测试
static void usage(std::string proc)
{std::cout << "Usage:\n\t" << proc << " serverip serverport\n"<< std::endl;
}
// ./udp_client serverip serverport
int main(int argc, char *argv[])
{if (argc != 3){usage(argv[0]);exit(USAGE_ERR);}std::string serverip = argv[1];uint16_t serverport = atoi(argv[2]);int sock = socket(AF_INET, SOCK_DGRAM, 0);if (sock < 0){std::cerr << "create socket error" << std::endl;exit(SOCKET_ERR);}// client 这里要不要bind? 要的!socket通信的本质[clientip:clientport, serverclient. serverport]// 要不要自己bind?不需要自己bind,os自动给我们进行bind!-- 为什么?client的port要随机让os分配防止client出现启动冲突// server为什么要自己bind -- 1. server的端口不能随意改变, 众所周知且不能随意改变;2. 同一家公司的port需要统一进行管理// 明确server是谁?struct sockaddr_in server;memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport);server.sin_addr.s_addr = inet_addr(serverip.c_str());while (true){// 用户输入std::string message;std::cout << "please Enter# ";std::cin >> message;// 什么时候bind?在我们首次系统调用发送数据的时候,OS会在底层随机选择clientport + 自己的IP 1. bind 2. 构建发送的数据报文// 发送sendto(sock, message.c_str(), message.size(), 0, (struct sockaddr *)&server, sizeof(server));// 接收char buffer[2048];struct sockaddr_in temp;socklen_t len = sizeof(temp);int n = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&temp, &len);if (n > 0){buffer[n] = 0;std::cout << "server echo# " << buffer << std::endl;}}return 0;
}
这样我们就完成了一个简单的UDP网络通信程序。
udp_v3
下面我们还需要对上述的UDP网络通信进行修改,在上述的网络通信程序中服务端在接收到客户端的信息之后立即进行了处理,然后将信息进行返回,但是我们想要让信息的处理与网络IO进行分离,在第三版中我们就进行对应的修改。我们在工作空间中定义了using func_t = std::function<std::string (std::string)>;
这样的参数为string,返回值为string的一个包装器,在udp_server类中新增了一个成员func_t service_;
来进行业务处理。在编写构造函数的时候将这个成员初始化,那么我们就可以在外部传入一个执行业务的方法,在外部定义好了这个执行的方法,在外部即udp_server.cc中将业务处理完毕之后再进行网络IO。
下面就是对上述版本的修改
// udp_server.hpp
// 在Start()中发送消息前执行业务处理
void Start()
{// ...// 做业务处理std::string response = service_(buffer);// 发sendto(sock_, response.c_str(), response.size(), 0, (struct sockaddr*)&peer, len); // 往文件中去写的时候,不需要携带\0
}
然后我们就在cpp文件中处理上层业务
// udp_server.cc
std::string transactionString(std::string request)
{std::string result;char c;for(auto & r : request){if (islower(r)) {c = toupper(r);result.push_back(c);}else {result.push_back(r);}}return result;
}static bool isPass(const std::string& command)
{bool pass = true;auto pos = command.find("mv");if (pos != std::string::npos) pass = false;pos = command.find("rm");if (pos != std::string::npos) pass = false;return pass;
}std::string execteCommand(std::string command)
{// FILE *popen(const char *command, const char *type);// 1. 创建管道// 2. 创建子进程// 3. 通过FILE*将结果直接返回,可以让用户以读取文件的访问,获得命令执行的结果// 安全检查if (!isPass(command)) return "bad";// 业务逻辑处理FILE* fp = popen(command.c_str(), "r");if (fp == nullptr) return "None";// 获取结果char line[2048];std::string result;while (fgets(line, sizeof(line), fp) != NULL){result += line;}return result;fclose(fp);
}int main()
{// ...// 通过传入第一个transactionString函数可以将我们客户端输入的小写字符,在服务端转换成大写然后在返回客户端unique_ptr<UdpServer> usvr(new UdpServer(transactionString, port)); // 这个业务方法就是将客户端输入的指令发送到服务端,在服务端执行后再将执行的结果返回给客户端// unique_ptr<UdpServer> usvr(new UdpServer(execteCommand, port));
}
大小写转换业务:
读取客户端指令的业务
udp_v4
上述第三版的程序还有一些问题就是,程序运行的时候收发的处理都在start()函数中,但是这样一旦阻塞在发送或者阻塞在收取的时候,假如有多个客户端要连接服务端,就会有影响。那么在第四版中我们就将结合前面的讲述过的基于环形队列的生产消费模型来将接受与发送分别使用两个线程来处理。在第四版中我们想要实现的是一个简易的udp多人聊天程序。
// udp_server.hpp
class UdpServer
{
public:UdpServer(uint16_t port = default_port) :port_(port){pthread_mutex_init(&lock, nullptr);p = new Thread(1, std::bind(&UdpServer::Recv, this)); // 这里传入接受与发送的函数时如果直接传入会发生报错,以为Recv与Broadcast都是类的方法,而类的方法是有隐含的this指针的,此时就可以使用bind函数将this指针这个成员先绑定,然后就可以正常的运行。c = new Thread(2, std::bind(&UdpServer::Broadcast, this));}void Start(){// ...c->run();p->run();}void addUser(const std::string& name, const struct sockaddr_in& peer) // 构建一个新用户{LockGuard lockguard(&lock);// onlineuser[name] = peer;auto iter = onlineuser.find(name); // 遍历检测是否存在该用户if (iter != onlineuser.end()) return;onlineuser.insert(std::pair<const std::string, const struct sockaddr_in>(name, peer));}void Recv(){// 服务器的正常工作char buffer[1024];while (true){// 收// ssize_t 实际写入的大小 recvfrom(int sockfd 绑定的套接字, void *buf 接受数据存放的缓冲区, size_t len 缓冲区长度, int flags 读取方式(0), struct sockaddr *src_addr 需struct sockaddr_in peer;socklen_t len = sizeof(peer); // 这里一定要写清楚,未来传入的缓冲区的大小int n = recvfrom(sock_, buffer, sizeof(buffer)-1/*因为这是以字符作为消息的类型,所以缓冲区预留一部分空间*/, 0, (struct sockaddr*)&peer, &len); // 消息的类型需要程序员if (n > 0) buffer[n] = '\0';else continue;std::cout << "recv done ..." << std::endl;// 提取client信息std::string clientip = inet_ntoa(peer.sin_addr); // 把一个四字节的IP转化为字符串uint16_t clientport = ntohs(peer.sin_port); // 将从网络中获取的端口号转换成主机std::cout << clientip << "-" << clientport << "#" << buffer << std::endl;// 构建一个用户并检查std::string name = clientip;name += "-";name += std::to_string(clientport);// 如果不存在就插入,如果存在,什么都不做addUser(name, peer);std::string message = name + " >> " + buffer;rq.push(message); // 将接收到的信息存放入生产消费中}}void Broadcast(){while (true){std::string sendstring;rq.pop(&sendstring); // 从生产消费模型中获取信息std::vector<struct sockaddr_in> v; // 获取所有的用户使用数组进行记录{LockGuard lockguard(&lock); // 使用锁进行保护防止产生冲突for (auto user : onlineuser){v.push_back(user.second);}}for (auto user : v) // 依次将信息发送出去{sendto(sock_, sendstring.c_str(), sendstring.size(), 0, (struct sockaddr *)&user, sizeof(user));}}}~UdpServer(){pthread_mutex_destroy(&lock);c->join();p->join();delete p;delete c;}
private:// ...std::unordered_map<std::string, struct sockaddr_in> onlineuser; // 添加使用用户RingQueue<std::string> rq; // 基于环形队列的生产消费模型pthread_mutex_t lock; // 互斥锁Thread *c, *p; // 创建生产者与消费者线程
};
对于客户端同样可以使用多线程
udp_client.cc
void* recver(void* args)
{pthread_detach(pthread_self());int sock = *static_cast<int*>(args);while (true){// 接收char buffer[2048];struct sockaddr_in temp;socklen_t len = sizeof(temp);int n = recvfrom(sock, buffer, sizeof(buffer)-1, 0, (struct sockaddr *)&temp, &len);if (n > 0){buffer[n] = 0;std::cout << buffer << std::endl;}}
}
int main(int argc, char *argv[])
{// ...pthread_t tid;pthread_create(&tid, nullptr, recver, &sock);while (true){// 用户输入std::string message;std::cerr << "please Enter# "; // 往2号文件发送// std::cin >> message;getline(std::cin, message);// 发送sendto(sock, message.c_str(), message.size(), 0, (struct sockaddr *)&server, sizeof(server));}return 0;
}
如上图所示就可以看到在右图中两个不同的客户端发送的消息都可以被看到。
相关文章:
网络编程套接字 | UDP套接字
前面的文章中我们叙述了网络编程套接字的一些预备知识点,从本文开始我们就将开始UDP套接字的编写。本文中的服务端与客户端都是在阿里云的云服务器进行编写与测试的。 udp_v1 在v1的版本中我们先来使用一下前面讲过得一些接口,简单的构建一个udp服务器…...
网络层IP协议
目录 前言 1.如何理解IP协议 2.IP协议格式 3.网段划分 4.特殊的IP地址 5.IP地址的数量限制 6.私有IP地址和公网IP地址 7.路由 总结 前言 在前面的文章中介绍了关于传输层常用的两个协议,UDP协议和TCP协议,当数据经过传输层之后,进入网…...
C++ Day4
目录 仿照string类,完成myString 类 思维导图 仿照string类,完成myString 类 #include <iostream> #include<cstring>using namespace std;class myString {private:char *str; //记录c风格的字符串int size; //记录…...
2024字节跳动校招面试真题汇总及其解答(二)
1. 微服务的好处,划分原则 微服务是软件架构的一种模式,它将应用程序划分为一系列小型、独立的服务。每个服务都提供一个单独的功能,并使用轻量级的接口相互通信。 微服务架构具有以下好处: 灵活性:微服务可以独立部署、扩展和更新,这使得它们能够随着业务需求的变化而…...
SpringBoot集成websocket(4)|(使用okhttp3实现websocket)
SpringBoot集成websocket(4)|(使用okhttp3实现websocket) 文章目录 SpringBoot集成websocket(4)|(使用okhttp3实现websocket)[TOC] 前言一、实现步骤1.实现步骤 二、websocket服务代…...
【MySQL】JDBC编程
MySQL-JDBC编程 文章目录 MySQL-JDBC编程Java的数据库编程JDBC工作原理JDBC的使用驱动包下载导入代码编写 Java的数据库编程 JDBC,即Java Database Connectivity,java数据库连接。是一种用于执行SQL语句的Java API,它是 Java中的数据库连接…...
数据结构——二叉树线索化遍历(前中后序遍历)
二叉树线索化 线索化概念: 为什么要转换为线索化 二叉树线索化是一种将普通二叉树转换为具有特殊线索(指向前驱和后继节点)的二叉树的过程。这种线索化的目的是为了提高对二叉树的遍历效率,特别是在不使用递归或栈的情况下进行遍历…...
GO语言网络编程(并发编程)Channel
GO语言网络编程(并发编程)Channel 1、Channel 1.1.1 Channel 单纯地将函数并发执行是没有意义的。函数与函数间需要交换数据才能体现并发执行函数的意义。 虽然可以使用共享内存进行数据交换,但是共享内存在不同的goroutine中容易发生竞态…...
c++day3
stack.h #ifndef STACK_H #define STACK_H #include <iostream> //#define max 128 using namespace std; class Stack { private:int* stack;//数组指针int top;//栈顶元素int max;//栈容量 public://构造函数Stack();//析构函数~Stack();//定义拷贝构造函数Stack(cons…...
算法通过村第六关-树青铜笔记|中序后序
文章目录 前言1. 树的常见概念2. 树的性质3. 树的定义与存储方式4. 树的遍历方式5. 通过序列构建二叉树5.1 前中序列恢复二叉树5.2 中后序列恢复二叉树 总结 前言 提示:瑞秋是个小甜心,她只喜欢被爱,不懂的去爱人。 --几米《你们 我们 他们》…...
C++动态内存管理+模板
💓博主个人主页:不是笨小孩👀 ⏩专栏分类:数据结构与算法👀 C👀 刷题专栏👀 C语言👀 🚚代码仓库:笨小孩的代码库👀 ⏩社区:不是笨小孩👀 🌹欢迎大…...
SQL 注入漏洞攻击
文章目录 1. 介绍2. 无密码登录3. 无用户名无密码登录4. 合并表获取用户名密码 1. 介绍 假设你用自己的用户名和密码登录了一个付费网站,网站服务器就会查询一下你是不是 VIP 用户,而用户数据都是放在数据库中的,服务器通常都会向数据库进行查…...
一篇五分生信临床模型预测文章代码复现——Figure 10.机制及肿瘤免疫浸润(四)
之前讲过临床模型预测的专栏,但那只是基础版本,下面我们以自噬相关基因为例子,模仿一篇五分文章,将图和代码复现出来,学会本专栏课程,可以具备发一篇五分左右文章的水平: 本专栏目录如下: Figure 1:差异表达基因及预后基因筛选(图片仅供参考) Figure 2. 生存分析,…...
Transformer 模型中常见的特殊符号
Transformer 模型中常见的特殊符号 通过代码一起理解一下 Transformer 模型中常见的特殊符号, 示例代码, special_tokens{unk_token: [UNK], sep_token: [SEP], pad_token: [PAD], cls_token: [CLS], mask_token: [MASK]}这段代码是定义了一个字典spec…...
C# halcon SubImage的使用
SubImage(HObject imageMinuend, HObject imageSubtrahend, out HObject imageSub, HTuple mult, HTuple add) 公式 x1imageMinuend此行此列的灰度 x2imageSubtrahend此行此列的灰度 则imageSub此行此列的灰度为;(x1-x2)*multadd 溢出裁剪 以byte图为例,小于0&a…...
每天几道Java面试题:异常机制(第三天)
目录 第三幕、第一场)异常机制面试题 友情提醒 背面试题很枯燥,加入一些戏剧场景故事人物来加深记忆。PS:点击文章目录可直接跳转到文章指定位置。 第三幕、 第一场)异常机制面试题 【面试官老吉,面试官潘安,面试者…...
Linux 中的 chattr 命令及示例
Linux 中的chattr命令是一个文件系统命令,用于更改目录中文件的属性。该命令的主要用途是使多个文件无法被超级用户以外的用户更改。管理员表示,众所周知,Linux 是一个多用户操作系统,一个用户有可能删除另一个用户非常关心的文件。为了避免这种情况,Linux 提供了“ chatt…...
LeetCode 2605. Form Smallest Number From Two Digit Arrays【数组,哈希表,枚举;位运算】1241
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
VoxWeekly|The Sandbox 生态周报|20230904
欢迎来到由 The Sandbox 发布的《VoxWeekly》。我们会在每周发布,对上一周 The Sandbox 生态系统所发生的事情进行总结。 如果你喜欢我们内容,欢迎与朋友和家人分享。请订阅我们的 Medium 、关注我们的 Twitter,并加入 Discord 社区…...
antd setFieldsValue 设置初始值无效AutoComplete 设置默认值失败
antd form setFieldsValue 设置初始值无效 解决方案 setTimeout(()>{setFieldsValue(values)},100)antd AutoComplete 设置默认值失败 defaultValue 设置无效 解决方案 设置value,搭配onChange来设置修改...
01-Redis核心数据结构与高性能原理
上一篇: 1.Redis安装 下载地址:http://redis.io/download 安装步骤: # 安装gcc yum install gcc# 把下载好的redis-5.0.3.tar.gz放在/usr/local文件夹下,并解压 wget http://download.redis.io/releases/redis-5.0.3.tar.gz…...
预防Dos攻击
Dos----拒绝服务攻击,一般是构造特殊的输入,使得后台的处理耗时远超正常水平,随着请求越来越多,后台服务越发疲于奔命,最后因资源耗尽,无法再接受新的请求,最终造成拒绝服务的效果。 特殊输入例…...
ant design的文档真的是一坨屎
很多基础设置 高傲的写都不写 要自己去index.d.ts里查 这就算了,为什么还有错的。。。。。 即使因为版本号而不同,起码把差异说明一下吧,直接丢个错的什么意思,。。。。。。。。 没点子功夫还真用不了 文档 进度条 Progress -…...
关于迁移学习的一点理解
举个栗子,老虎图片的数量非常少,可以让网络先学会识别猫的图片 1、预训练模型 内容:利用在 ImageNet1000 数据集训练好的模型,将所需的模型参数下载,嵌入到对应的网络架构中,使用对预训练模型的搭建。目前P…...
【力扣周赛】第 361 场周赛(⭐前缀和+哈希表 树上倍增、LCA⭐)
文章目录 竞赛链接Q1:7020. 统计对称整数的数目竞赛时代码——枚举预处理 Q2:8040. 生成特殊数字的最少操作(倒序遍历、贪心)竞赛时代码——检查0、00、25、50、75 Q3:2845. 统计趣味子数组的数目竞赛时代码——前缀和…...
解决 Android 依赖冲突
解决办法 问题原因就是,各个模块所有的依赖(递归)的 jar 包最后都会加载到安卓的项目中,你可以选择 project 形式查看 External Libraries,都在这了。所以解决问题关键就是干掉冲突,剩下一个就行了…...
前端设计模式基础笔记
前端设计模式是指在前端开发中经常使用的一些解决问题的模式或思想。它们是经过实践证明的最佳实践,可以帮助我们更好地组织和管理我们的代码。 一、单例模式(Singleton Pattern) 单例模式是一种创建型模式,它保证一个类只有一个…...
Python项目开发:Flask基于Python的天气数据可视化平台
目录 步骤一:数据获取 步骤二:设置Flask应用程序 步骤三:处理用户输入和数据可视化 步骤四:渲染HTML模板 总结 在这个数字化时代,数据可视化已经成为我们理解和解释信息的重要手段。在这个项目中,我们…...
Dell 服务器常见报错信息汇总
Dell 服务器常见报错汇总 如果有别的报错信息欢迎补充...
算法通关村-----贪心面试大热门之区间问题
判断区间是否重叠 问题描述 给定一个会议时间安排数组intervals,每个会议时间都包括开始时间和结束时间,intervals[i] [starti,endi],请你判断一个人是否能够参加这里面的全部会议。详见leetcode252 问题分析 先将会议安排数组按照开始时间排序&…...
网站模块是指什么地方/交换链接营销的典型案例
1.选中项目后选择 open in Terminal 2.1键入指令:mvn clean install -Dmaven.test.skiptrue 2.2或者通过maven打包 指令 clean package -Dmaven.test.skiptrue 3.会在存放项目的target下生成项目的jar文件 4.在输入框输入cmd 5.windos在黑窗口下输入指令&#x…...
附近计算机培训班咨询/seo关键词seo排名公司
2021~2021计算机基础知识练习题 20212021计算机基础知识练习题北京联合大学20212021计算机基础知识练习题一、选择题1.记录在存储介质上的一组相关信息的集合称为______。A)程序 B)磁盘 C)软件 D)文件2.当一个文件更名后,文件的内容会______。A)完全消失 B)完全不变…...
简单的做网站软件有啥/电商中seo是什么意思
一、问题的起源 软件环境:Unity 2017.3.0f3,Visual Studio 2013 问题描述:在Unity中创建C#脚本后,准备双击打开进行编辑时,出现了Fatal Error。 二、问题的分析 照着它所给的链接下载了Mono,解压安装后重启…...
怎么查看网站用什么做的/aso优化师
自动驾驶到底怎么了? 进入2021年,在驾驶辅助技术方面,随着算法的继续迭代、算力的持续提升、更多传感器的加入,在驾驶员保持时刻监管的情况下,无论是功能升级还是场景的突破,都已经取得了很大进展…...
网站建设好后怎样形成app/seo职业培训学校
主要功能是更方便的添加/删除/更新RPM包. 它能自动解决包的倚赖性问题. 它能便于管理大量系统的更新问题 一、yum list|more 列出所有包文件,可搭配grep查询软件包,如yum list |grep kernel 二、yum info xxx 显示包xxx详…...
网站管理与建设/seo研究中心道一老师
Jconsole是JDK自带的监控工具,在JDK/bin目录下可以找到。它用于连接正在运行的本地或者远程的JVM,对运行在java应用程 序的资源消耗和性能进行监控,并画出大量的图表,提供强大的可视化界面。而且本身占用的服务器内存很小…...