【linux网络编程】| socket套接字 | 实现UDP协议聊天室
前言:本节内容将带友友们实现一个UDP协议的聊天室。 主要原理是客户端发送数据给服务端。 服务端将数据再转发给所有链接服务端的客户端。 所以, 我们主要就是要实现客户端以及服务端的逻辑代码。 那么, 接下来开始我们的学习吧。
ps:本节内容建议了解socket套接字的接口的友友们进行观看哦,本节内容中涉及到的接口都不会讲解, 直接就用了。
目录
整体代码
Udpclient
UdpServer
main(配合UdpServer, UdpServer的入口)
准备文件
实现步骤
实现服务端客户端的收发消息
Udpserver
Init函数
run函数
UdpServer析构
Udpclient
实现客户端之间的聊天功能
Udpserver
Udpclient
运行结果
整体代码
先上整体代码:
Udpclient
#include<iostream>
using namespace std;
#include<string>
#include<sys/types.h>
#include"Log.hpp"
#include<sys/socket.h>
#include<pthread.h>
#include<arpa/inet.h>
#include<string.h>
#include<netinet/in.h>
Log lg;class ThreadData
{
public:sockaddr_in server;int sockfd;
};void* recv_message(void* args)
{char buffer[1024];ThreadData* td = static_cast<ThreadData*>(args); while (true){//接收数据sockaddr_in temp;socklen_t len;string info;ssize_t s = recvfrom(td->sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr*)&temp, &len);if (s < 0){lg(Error, "recv error, error: %d, strerror: %s", errno, strerror(errno));continue;}buffer[s] = 0;info = buffer;cout << info << endl;}}void* send_message(void* args)
{ThreadData* td = static_cast<ThreadData*>(args);string message;while (true){ getline(cin, message); //获取数据//发送数据sendto(td->sockfd, message.c_str(), message.size(), 0, (sockaddr*)&td->server, sizeof(td->server));}
}int main(int argc, char* argv[])
{if (argc != 3){cout << "Client server" << endl;}//先拿到套接字的参数string serverip = argv[1];uint16_t serverport = stoi(argv[2]);ThreadData td;//创建套接字与打开网卡memset(&td.server, 0, sizeof(td.server));td.server.sin_family = AF_INET;td.server.sin_port = htons(serverport);td.server.sin_addr.s_addr = inet_addr(serverip.c_str());td.sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建文件描述符, 网卡的文件描述符, 网络传输就是使用网络文件描述符找到对应的文件内的数据if (td.sockfd < 0){lg(Error, "client create sockfd error, errno: %d, strerror: %s", errno, strerror(errno));exit(1);}//创建线程, 然后运行线程, 等待线程pthread_t recv, send;pthread_create(&recv, nullptr, recv_message, &td);pthread_create(&send, nullptr, send_message, &td);pthread_join(recv, nullptr);pthread_join(send, nullptr);close(td.sockfd);return 0;
}
UdpServer
#include<iostream>
using namespace std;
#include<sys/types.h>
#include<string>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<strings.h>
#include"Log.hpp"
#include<functional>
#include<netinet/in.h>
#include<unordered_map>int defaultport = 8080;
string defaultip = "0.0.0.0";using func_t = function<string(string, sockaddr_in&, unordered_map<string, sockaddr_in>&)>;
Log lg;enum
{SockError = 2,BindError = 3,RecvError = 4,
};class UdpServer
{
public:UdpServer(uint16_t port = defaultport) : port_(port), ip_(defaultip), isrunning_(false){}void Init(){//先创建套接字变量并且完成初始化。 然后就创建网卡文件sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port_);local.sin_addr.s_addr = inet_addr(ip_.c_str());sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ < 0){lg(Fatal, "create sock error, errno: %d, strerror: %s", errno, strerror(errno));exit(SockError);}lg(Info, "create sock success");//绑定if (bind(sockfd_, (sockaddr*)&local, sizeof(local)) < 0) {lg(Fatal, "bind error, errno: %d, strerror: %s", errno, strerror(errno));exit(BindError);}lg(Info, "bind success");}void BroadCast(string message, unordered_map<string, sockaddr_in>& clients){cout << "1 "<< endl;for (auto& e : clients){sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)&e.second, sizeof(e.second));}cout << "2 " << endl;}void run(func_t func){isrunning_ = true;char inbuffer[1024];while (isrunning_){memset(inbuffer, 0, sizeof(inbuffer));sockaddr_in client;socklen_t client_len;memset(&client, 0, sizeof(client));//接收数据的同时监听到客户端的来源ssize_t s = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (sockaddr*)&client, &client_len);if (s < 0) {lg(Waring, "recvfrom error, errno: %d, strerror: %s", errno, strerror(errno));continue;}inbuffer[s] = 0;//处理数据//创建套接字, 用来监听是哪一个客户端string message = inbuffer;message = func(message, client, clients);//处理完成后, 返回发送给客户端BroadCast(message, clients);// sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)&client, sizeof(client));}}~UdpServer(){if (sockfd_ > 0) close(sockfd_); }
private:int sockfd_;uint16_t port_;string ip_;bool isrunning_;unordered_map<string, sockaddr_in> clients;};
main(配合UdpServer, UdpServer的入口)
#include"UdpServer.hpp"
#include<memory>string Handler(string message, sockaddr_in& client, unordered_map<string, sockaddr_in>& clients)
{string tmp = inet_ntoa(client.sin_addr) + to_string(client.sin_port);if (!clients.count(tmp)){clients[tmp] = client; cout << "ip " << inet_ntoa(client.sin_addr) << " : port " << client.sin_port << " has add in talk room" << endl;}message = "[" + string(inet_ntoa(client.sin_addr)) + ":" + to_string(client.sin_port) + "]#: " + message; return message;
}int main(int argc, char* argv[])
{if (argc != 2){cout << "has return" << endl;return 1;}//uint16_t serverport = stoi(argv[1]); unique_ptr<UdpServer> svr(new UdpServer(serverport));//svr->Init();svr->run(Handler);return 0;
}
准备文件
我们要准备三个文件
- Udpclient.cc——用来运行起来客户端
- UdpServer.hpp——用来实现服务端的各种接口
- main.cc——用来运行起来服务端
除了这三个主要的文件。 其实博主还准备了两个可以忽略的文件(为了方便)。 一个是博主自己写的日志程序, 用来打印日志。 一个是makefile, 方便编译。
如果没有日志程序的话,打印错误信息时直接cout, printf打印即可。 makefile建议带上, 方便编译养成好习惯。
实现步骤
注意, 一步到位是很难的。 所以我们先实现简单的功能, 再实现困难的功能。
这里简单的功能就是,先让客户端能够将数据发给服务端了, 然后服务端接收到消息后再将数据返回给客户端。
这里困难的功能就是当多个客户端如何看到互相的信息。然后如何能够一遍发信息,一边收信息。
实现服务端客户端的收发消息
Udpserver
实现逻辑:Udpserver.hpp中封装一个类。这个类里面封装一些接口, 然后我们在main函数中创建类对象, 在执行接口操作。
所以, 先封装一个类, 将要实现的接口以及要用到的变量写上, 实现一个框架:
#include<iostream>
using namespace std;
#include<string>int defaultport = 8080; //默认的端口号,我们要创建一个默认的端口号
string defaultip = "0.0.0.0"; //在服务器中使用套接字的时候, bind函数不能绑定公网IP, 因为
//服务器的公网IP可能是虚拟的, 注意,IP地址是和网卡挂钩的, 一个网卡只能有一个IP地址。
//绑定ip地址就是说在绑定网卡,也就是说绑定某个IP地址后就只能监听这一个网卡的消息了。 但是
//有些机器是有很多张网卡的, 所以就有一个默认IP:0.0.0.0, 绑定这个IP就能监听在本机器下面
//所有的网卡的信息。 Log lg;class UdpServer
{
public:UdpServer(uint16_t port = defaultport) : port_(port), ip_(defaultip), isrunning_(false){}void Init(){}void run(func_t func){}~UdpServer(){}
private:int sockfd_; //服务端的网卡文件的编号uint16_t port_; //服务器起来后的端口号string ip_; //服务器起来的时候所在的ip地址bool isrunning_; //服务器是否正在运行};
下面是main.cpp里面的内容, 直接启动服务端。
#include"UdpServer.hpp"
#include<memory>int main(int argc, char* argv[])
{if (argc != 2){cout << "has return" << endl;return 1;}//uint16_t serverport = stoi(argv[1]); unique_ptr<UdpServer> svr(new UdpServer(serverport));//svr->Init();svr->run();return 0;
}
Init函数
Udpserver里面的Init函数, 这个函数用来绑定服务端的套接字的。 什么是绑定? 博主目前的理解就是将我们运行的服务端这个程序能够和网卡建立起关系。
这个关系中, 关系的两端是我们运行的服务端程序和socket网卡文件(网卡文件就代表了网卡)。关系的纽带是ip地址和端口号。 利用ip地址和端口号来将我们的服务端程序绑定给网卡, 这个时候因为网卡的工作性质, 其他的进程都不能再绑定网卡了, 直到我们的服务端退出。
void Init(){//先创建套接字变量并且完成初始化。 然后就创建网卡文件sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port_);local.sin_addr.s_addr = inet_addr(ip_.c_str());sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ < 0){lg(Fatal, "create sock error, errno: %d, strerror: %s", errno, strerror(errno));exit(SockError);}lg(Info, "create sock success");//绑定if (bind(sockfd_, (sockaddr*)&local, sizeof(local)) < 0) {lg(Fatal, "bind error, errno: %d, strerror: %s", errno, strerror(errno));exit(BindError);}lg(Info, "bind success");}
run函数
我们这里思考一个问题, 我们要实现的其实是服务端与客户端之间收发消息。 所以, 我们就要客户端先发, 然后服务端收消息。
然后! 服务端收到消息将消息 处理一下 再将消息发回客户端。
所以,这个过程中服务端有三个主要的动作, 一个是收,一个是处理, 一个是发。
然后我们的处理怎么处理, 我们可以将处理动作暴露出去, 交给main.cpp来决定。 ——利用回调函数, main.cpp中将要执行的动作作为函数传给run函数。
如下为接口:
//这里的func_t是一个回调函数的类型。 什么类型, 使用包装器包装的!注意//包含头文件functionalusing func_t = function<string(string)>; void run(func_t func){isrunning_ = true;char inbuffer[1024];while (isrunning_){memset(inbuffer, 0, sizeof(inbuffer));sockaddr_in client;socklen_t client_len;memset(&client, 0, sizeof(client));//接收数据的同时监听到客户端的来源ssize_t s = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (sockaddr*)&client, &client_len);if (s < 0) {lg(Waring, "recvfrom error, errno: %d, strerror: %s", errno, strerror(errno));continue;}inbuffer[s] = 0;//处理数据//创建套接字, 用来监听是哪一个客户端string message = inbuffer;message = func(message);//这里的处理使用一个外部的接口//处理完成后, 返回发送给客户端sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)&client, sizeof(client));}}
UdpServer析构
析构函数不解释
~UdpServer(){if (sockfd_ > 0) close(sockfd_); }
Udpclient
客户端就是给对应的服务端发送数据。 数据被服务端处理后接收即可:
#include<iostream>
#include<cstdlib>
#include<unistd.h>
using namespace std;
#include<sys/types.h>
#include<strings.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<cstring>
#include<string>//./udpclient serverip serverport
int main(int argc, char* argv[])
{if (argc != 3){cout << "has return" << endl;return 1;}//string serverip = argv[1];uint16_t serverprot = stoi(argv[2]);//创建套接字struct sockaddr_in server;bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverprot);server.sin_addr.s_addr = inet_addr(serverip.c_str());socklen_t serlen = sizeof(server);int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){cout << "socker error" << endl; return 1;}string message;char buffer[1024];while(true){ cout << "please Enter@:" << endl;getline(cin, message); //发送数据sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr*)&server, serlen);cout << "yes" << endl;//接收数据sockaddr_in temp;socklen_t socklen;ssize_t sz = recvfrom(sockfd, (void*)buffer, sizeof(buffer) - 1, 0, (sockaddr*)&temp, &socklen); //sockfd其实就是网卡的pidif(sz > 0){buffer[sz] = 0;cout << buffer << endl;}}close(sockfd);return 0;
}
实现客户端之间的聊天功能
Udpserver
实现客户端之间的聊天可是说是在上面的代码中改两个地方。 一个是创建一个哈希表存储有多少客户端连接了服务端。 然后以后发消息就直接便利整个哈希表, 然后将数据发给每一个客户端。 如下:
#include<iostream>
using namespace std;
#include<sys/types.h>
#include<string>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<strings.h>
#include"Log.hpp"
#include<functional>
#include<netinet/in.h>
#include<unordered_map>int defaultport = 8080;
string defaultip = "0.0.0.0";//包装类要进行修改一下
using func_t = function<string(string, sockaddr_in&, unordered_map<string, sockaddr_in>&)>; Log lg;enum
{SockError = 2,BindError = 3,RecvError = 4,
};class UdpServer
{
public:UdpServer(uint16_t port = defaultport) : port_(port), ip_(defaultip), isrunning_(false){}//Init不变void Init(){//先创建套接字变量并且完成初始化。 然后就创建网卡文件sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port_);local.sin_addr.s_addr = inet_addr(ip_.c_str());sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ < 0){lg(Fatal, "create sock error, errno: %d, strerror: %s", errno, strerror(errno));exit(SockError);}lg(Info, "create sock success");//绑定if (bind(sockfd_, (sockaddr*)&local, sizeof(local)) < 0) {lg(Fatal, "bind error, errno: %d, strerror: %s", errno, strerror(errno));exit(BindError);}lg(Info, "bind success");}//遍历哈希表,将数据分发给所有的客户端void BroadCast(string message, unordered_map<string, sockaddr_in>& clients){cout << "1 "<< endl;for (auto& e : clients){sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)&e.second, sizeof(e.second));}cout << "2 " << endl;}void run(func_t func){isrunning_ = true;char inbuffer[1024];while (isrunning_){memset(inbuffer, 0, sizeof(inbuffer));sockaddr_in client;socklen_t client_len;memset(&client, 0, sizeof(client));//接收数据的同时监听到客户端的来源ssize_t s = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (sockaddr*)&client, &client_len);if (s < 0) {lg(Waring, "recvfrom error, errno: %d, strerror: %s", errno, strerror(errno));continue;}inbuffer[s] = 0;//处理数据//创建套接字, 用来监听是哪一个客户端string message = inbuffer;message = func(message, client, clients);//这里的处理使用一个外部的接口//处理完成后, 返回发送给客户端BroadCast(message, clients);}}~UdpServer(){if (sockfd_ > 0) close(sockfd_); }
private:int sockfd_;uint16_t port_;string ip_;bool isrunning_;unordered_map<string, sockaddr_in> clients; //添加哈希表};
#include"UdpServer.hpp"
#include<memory>//main.cc主要修改就是Handler函数, 我们要通过client里面的ip地址和端口号作为key,client作为value,然后放入哈希表。 同时将message处理一下,方便我们观看结果。
string Handler(string message, sockaddr_in& client, unordered_map<string, sockaddr_in>& clients)
{string tmp = inet_ntoa(client.sin_addr) + to_string(client.sin_port);if (!clients.count(tmp)){clients[tmp] = client; cout << "ip " << inet_ntoa(client.sin_addr) << " : port " << client.sin_port << " has add in talk room" << endl;}message = "[" + string(inet_ntoa(client.sin_addr)) + ":" + to_string(client.sin_port) + "]#: " + message; return message;
}// int main(int argc, char* argv[])
{if (argc != 2){cout << "has return" << endl;return 1;}//uint16_t serverport = stoi(argv[1]); unique_ptr<UdpServer> svr(new UdpServer(serverport));//svr->Init();svr->run(Handler);return 0;
}
Udpclient
#include<iostream>
using namespace std;
#include<string>
#include<sys/types.h>
#include"Log.hpp"
#include<sys/socket.h>
#include<pthread.h>
#include<arpa/inet.h>
#include<string.h>
#include<netinet/in.h>
Log lg;class ThreadData
{
public:sockaddr_in server;int sockfd;
};//数据接收函数
void* recv_message(void* args)
{char buffer[1024];ThreadData* td = static_cast<ThreadData*>(args); while (true){//接收数据sockaddr_in temp;socklen_t len;string info;ssize_t s = recvfrom(td->sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr*)&temp, &len);if (s < 0){lg(Error, "recv error, error: %d, strerror: %s", errno, strerror(errno));continue;}buffer[s] = 0;info = buffer;cout << info << endl;}}//数据发送函数
void* send_message(void* args)
{ThreadData* td = static_cast<ThreadData*>(args);string message;while (true){ getline(cin, message); //获取数据//发送数据sendto(td->sockfd, message.c_str(), message.size(), 0, (sockaddr*)&td->server, sizeof(td->server));}
}int main(int argc, char* argv[])
{if (argc != 3){cout << "Client server" << endl;}//先拿到套接字的参数string serverip = argv[1];uint16_t serverport = stoi(argv[2]);ThreadData td;//创建套接字与打开网卡memset(&td.server, 0, sizeof(td.server));td.server.sin_family = AF_INET;td.server.sin_port = htons(serverport);td.server.sin_addr.s_addr = inet_addr(serverip.c_str());td.sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建文件描述符, 网卡的文件描述符, 网络传输就是使用网络文件描述符找到对应的文件内的数据if (td.sockfd < 0){lg(Error, "client create sockfd error, errno: %d, strerror: %s", errno, strerror(errno));exit(1);}//创建线程, 然后运行线程, 等待线程pthread_t recv, send;pthread_create(&recv, nullptr, recv_message, &td);pthread_create(&send, nullptr, send_message, &td);pthread_join(recv, nullptr);pthread_join(send, nullptr);close(td.sockfd);return 0;
}
运行结果
最后就是运行结果, 运行结果就是下图了, 我们已经能够成功的进行两个客户端之间的远程交流
——————以上就是本节全部内容哦, 如果对友友们有帮助的话可以关注博主, 方便学习更多知识哦!!!
相关文章:

【linux网络编程】| socket套接字 | 实现UDP协议聊天室
前言:本节内容将带友友们实现一个UDP协议的聊天室。 主要原理是客户端发送数据给服务端。 服务端将数据再转发给所有链接服务端的客户端。 所以, 我们主要就是要实现客户端以及服务端的逻辑代码。 那么, 接下来开始我们的学习吧。 ps:本节内容…...

第二届开放原子大赛-开源工业软件算法集成大赛即将启动!
第二届开放原子大赛-开源工业软件算法集成大赛作为开放原子开源基金会组织举办的开源技术领域专业赛事,聚焦开源底座框架平台建设,通过组件化集成的开发模式,丰富平台功能模块,拓展其应用场景,以此促进工业软件生态的繁…...
PXC集群(Percona XtraDB Cluster )
一、简介 基于Galera Cluster技术的开源分布式数据库解决方案,它允许你在多个MySQL服务器之间创建一个同步的多主复制集群。 特点: * 多主复制架构: PXC集群支持多主复制,每个节点都可以同时读写数据,这使得应用程序可以更灵活地进行负载均衡和高可用性设置。* 同步复制:…...

分布式光伏是什么意思?如何高效管理?
分布式光伏系统是指在用户现场或靠近用电现场配置较小的光伏发电供电系统,以满足特定用户的需求。根据通知,分布式光伏系统主要有以下几类定义: 10kV以下电压等级接入,且单个并网点总装机容量不超过6MW的分布式电源:这…...
提问GPT
1 理解GPT AI模型即采用深度学习技术的人工神经网络。 你不会被AI取代,而是会被熟练运用AI的人取代 1.1 问答或对话是普通用户与这一轮新AI产品的典型交互方式。 GPT生成式预训练转换器 了解当前GPT产品的形式: 通用聊天机器人…...

李飞飞团队新突破:低成本高泛化机器人训练法,零样本迁移成功率90%!
在机器人训练中,如何高效地利用模拟环境一直是研究者们关注的重点问题。 近日,美国斯坦福大学李飞飞教授团队提出了一种突破性的“数字表亲”(digital cousins)概念。这一创新方法既保留了数字孪生的优势,又大大降低了…...
PHP内存马:不死马
内存马概念 内存马是无文件攻击的一种常用手段,利用中间件的进程执行某些恶意代码。首先要讲的是PHP不死马,实质上就是直接用代码弄一个死循环,强占一个 PHP 进程,并不间断的写一个PHP shell,或者执行一段代码。 不死…...

【python】OpenCV—Connected Components
文章目录 1、任务描述2、代码实现3、完整代码4、结果展示5、涉及到的库函数6、参考 1、任务描述 基于 python opencv 的连通分量标记和分析函数,分割车牌中的数字、号码、分隔符 cv2.connectedComponentscv2.connectedComponentsWithStatscv2.connectedComponents…...

【优选算法篇】前缀之序,后缀之章:于数列深处邂逅算法的光与影
文章目录 C 前缀和详解:基础题解与思维分析前言第一章:前缀和基础应用1.1 一维前缀和模板题解法(前缀和)图解分析C代码实现易错点提示代码解读题目解析总结 1.2 二维前缀和模板题解法(二维前缀和)图解分析C…...
win10 更新npm 和 node
win10 更新npm 和 node win10 更新 npm winR 输入cmd,打开命令行,并输入如下 # 查看当前npm版本 npm -v # 清缓存 npm cache clean --force # 强制更新npm,试过npm update -g,没起作用,版本没变化 npm install -g …...

搜索引擎算法更新对网站优化的影响与应对策略
内容概要 随着互联网的不断发展,搜索引擎算法也在不断地进行更新和优化。了解这些算法更新的背景与意义,对于网站管理者和优化人员而言,具有重要的指导意义。不仅因为算法更新可能影响到网站的排名,还因为这些变化也可能为网站带…...

使用 Q3D 计算芯片引线的 AC 和 DC R 和 L
摘要: 模具经常用于电子行业。了解其导联的寄生特性对于设计人员来说很重要。Q3D 是计算 RLCG 的完美工具。它可用于高速板或低频电力电子设备。 在下面的视频中,我们展示了如何修改几何结构、设置模型和检查结果。 详细信息: 几何图形可以在 Q3D 中创建,也可以作为不同…...
前端_008_Vite
文章目录 Vite项目结构依赖构建插件 官网:https://vitejs.cn/vite3-cn/guide/ 一句话简介:前端的一个构建工具 Vite项目结构 index.html package.json vite.config.js public目录 src目录 #新建一个vite项目 npm create vitelatest原有项目引入vite需要…...

ssm007亚盛汽车配件销售业绩管理统(论文+源码)_kaic
本科毕业设计论文 题目:亚盛汽车配件销售业绩管理系统设计与实现 系 别: XX系(全称) 专 业: 软件工程 班 级: 软件工程15201 学生姓名: 学生学号: 指导教师&am…...
如何使用python完成时间序列的数据分析?
引言 时间序列分析是统计学和数据分析中的一个重要领域,广泛应用于经济学、金融、气象学、工程等多个领域。 时间序列数据是按时间顺序排列的一系列数据点,通常用于分析数据随时间的变化趋势。 本文将介绍时间序列分析的基本概念、常用方法以及如何使用Python进行时间序列…...
数字ic设计,Windows/Linux系统,其他相关领域,软件安装包(matlab、vivado、modelsim。。。)
目录 一、总述 二、软件列表 1、modelsim_10.6c 2、notepad 3、matlab 4、Visio-Pro-2016 5、Vivado2018 6、VMware15 7、EndNote X9.3.1 8、Quartus 9、pycharm 10、CentOS7-64bit 一、总述 过往发了很多数字ic设计领域相关的内容,反响也很好。 最近…...

SD-WAN分布式组网:构建高效、灵活的企业网络架构
随着企业数字化转型的深入,分布式组网逐渐成为企业网络架构中的核心需求。无论是跨区域的分支机构互联,还是企业与云服务的连接,如何在不同区域实现高效、低延迟的网络传输,已成为业务成功的关键。SD-WAN(软件定义广域…...

Task :prepareKotlinBuildScriptModel UP-TO-DATE,编译卡在这里不动或报错
这里写自定义目录标题 原因方案其他思路 原因 一般来说,当编译到这个task之后,后续是要进行一些资源的下载的,如果你卡在这边不动的话,很有可能就是你的IDE目前没有办法进行下载。 方案 开关一下IDE内部的代理,或者…...

unseping攻防世界
源码分析 <?php highlight_file(__FILE__);//代码高亮 class ease{//声明了两个私有属性:保存要调用的方法的名称和保存该方法的参数。$method,$argsprivate $method;private $args;//构造函数在实例化类的对象时初始化,即为对象成员变量赋初始值。…...
大厂面试真题-简单描述一下SpringBoot的启动过程
SpringBoot的启动流程是一个复杂但有序的过程,它涉及多个步骤和组件的协同工作。以下是SpringBoot启动流程的详细解析: 一、启动main方法 当SpringBoot项目启动时,它会在当前工作目录下寻找有SpringBootApplication注解标识的类,…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...