Linux网络套接字之UDP网络程序

 (。・∀・)ノ゙嗨!你好这里是ky233的主页:这里是ky233的主页,欢迎光临~icon-default.png?t=N7T8https://blog.csdn.net/ky233?type=blog

点个关注不迷路⌯'▾'⌯

 实现一个简单的对话发消息的功能!

目录

一.新增的接口:

1.socket

2.bing

3.inet_addr

4.recvform

5.inet_ntoa

5.sendto

6.popen

二、初步代码以及结果

1.udp_server.hpp

2.udp_server.cc 

3.udp_client

4.log.hpp

5.结果 

三、爆改多线程

1.udp_client.cc

2.udp_server.cc

3.udp_server.hpp

 4.thread.hpp

5.结果


一.新增的接口:

1.socket

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>int socket(int domain, int type, int protocol);
  • 参数一:叫做域,用来判断是那个类型的,AF_UNIX, AF_LOCAL(用于本地通信)AF_INET(用于ipv4的网络通信)
  • 参数二:类型,通信的种类是什么,SOCK_DGRAM(套接字的类别,数据报的方式)
  • 参数三:协议,比如用AF_INET,SOCK_DGRAM,一般直接写0
  •  创建成功会得到一个文件描述符,失败返回-1

2.bing

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
  • 参数一:创建的套接字
  • 参数二:填充sockaddr结构体
  • 参数三:所传入这个结构体对象的长度

3.inet_addr

#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>
n_addr_t inet_addr(const char *cp);
  • 将点分十进制转换成四字节,并且将主机序列转换成网络序列
  • 参数一:传入的ip

4.recvform

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
  • 用于从套接字接收数据。该函数通常与无连接的数据报服务
  • 参数一:套接字
  • 参数二和参数三:读取数据的缓冲区,用于存放读取到的数据,len叫做最终的大小
  • 参数四:读取的方式,0为阻塞的方式读取
  • 参数五和参数六:是输出型参数,我们还要知道是谁给我们发的消息

5.inet_ntoa

#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>
char *inet_ntoa(struct in_addr in);
  • 将点分四字节转换成点分十进制,并且将网络序列转换成主机序列
  • 参数一:从网络中获取到的ip

5.sendto

#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
  • 参数一:套接字
  • 参数二和参数三:要发送的数据和长度
  • 参数四:默认为0,阻塞
  • 参数五:要把数据发给谁,
  • 参数六:这个缓冲区的长度是多少

6.popen

#include <stdio.h>FILE *popen(const char *command, const char *type);

二、初步代码以及结果

1.udp_server.hpp

#ifndef _UDP_SERVER_HPP
#define _UDP_SERVER_HPP#include <iostream>
#include <string>
#include <sys/types.h>        
#include <sys/socket.h>
#include "log.hpp"
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <cstdio>
#include <unistd.h>#define SIZE 1024class UDPServer
{
public:UDPServer(uint16_t port,std::string ip=""):port_(port),ip_(ip),sock_(-1){}bool initServer(){//这里开始使用网络部分//1.创建套接字sock_=socket(AF_INET,SOCK_DGRAM,0);if(sock_<0){logMessage(FATAL,"%d:%s",errno,strerror(errno));exit(2);}//2.bind绑定:将用户设置的ip和端口号在内核中和我们的进程强关联//"192.168.1.0"->点分十进制//以.来分隔,每个区域的取值范围为0——255,//正好为1字节,四个区域理论上需要四字节//所以我们的看的时候会由4字节显示,转换为点分十进制//初始化结构体完成struct sockaddr_in local;bzero(&local,sizeof(local));//填充结构体local.sin_family=AF_INET;//服务器的IP和端口号,未来也是要发送给对方主机才能互相通信的//所以要先把数据发送到网络,要用htonslocal.sin_port=htons(port_);//同上要先把点分十进制转换成四字节ip//还需要要把四字节主机序列,转换成网络序列//所以用inet_addr一次性转成网络四字节序列//local.sin_addr.s_addr=inet_addr(ip_.c_str());//一般情况下,只要是这个端口的,那么我们就直接全部都接受,而不是指定端口local.sin_addr.s_addr = ip_.empty() ? INADDR_ANY : inet_addr(ip_.c_str());//这里需要做强转,因为bind需要的是sockaddr类型而不是sockaddr_in类型if(bind(sock_,(struct sockaddr*)&local,sizeof(local))<0){logMessage(FATAL,"%d:%s",errno,strerror(errno));exit(2);}//至此初始化服务器写完,首先创建套接字,接着用bind来绑定ip和端口号写进内核中logMessage(NORMAL, "init udp server done ... %s", strerror(errno));return true;}void strat(){//作为一款网络服务器,是永远不退出的!// 服务器启动-> 进程 -> 常驻进程 -> 永远在内存中存在,除非挂了!//echo服务器,主机给我们发送消息,我们原封不动的返回char buffer[SIZE];for( ; ;){//1.读取数据//注意peer,纯输出型参数struct sockaddr_in peer;bzero(&peer,sizeof(peer));//输入:peer 缓冲区大小//输入:实际读到的peer大小//所以len的大小要为实际的peer大小socklen_t len = sizeof(peer);//这样就把数据读取到buffer里了ssize_t s= recvfrom(sock_,&buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);if(s>0){buffer[s]=0;//我们目前数据当作字符串//1.输出发送的数据信息//2.是谁?提取!uint16_t cil_port=ntohs(peer.sin_port);//从网络中来的,所以要进行转成主机端口号std::string cli_p=inet_ntoa(peer.sin_addr);//将点分四字节转换成点分十进制,并且将网络序列转换成主机序列printf("[%s:%d]# %s\n",cli_p.c_str(),cil_port,buffer);}//2.分析和处理数据//3.写回数据sendto(sock_,buffer,sizeof(buffer),0,(struct sockaddr*)&peer,len);}}~UDPServer(){if(sock_>=0){close(sock_);}}private:
uint16_t port_;
std::string ip_;
int sock_;
};#endif

2.udp_server.cc 

#include "udp_server.hpp"
#include <memory>
#include <cstdlib>static void usage(std::string proc)
{std::cout << "\nUsage: " << proc << " port\n" << std::endl;
}int main(int argc,char *argv[])
{//检查传入ip和端口号是否错误if(argc!=2){usage(argv[0]);exit(1);}//初始化服务器,利用unique_ptruint16_t port=atoi(argv[1]);//std::string ip=argv[1];std::unique_ptr<UDPServer> svr(new UDPServer(port));svr->initServer();svr->strat();return 0;
}

3.udp_client

#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <memory>
#include "thread.hpp"static void usage(std::string proc)
{std::cout << "\nUsage: " << proc << " serverIp serverPort\n"<< std::endl;
}int main(int argc, char *argv[])
{if (argc != 3){usage(argv[0]);exit(1);}int sock = socket(AF_INET, SOCK_DGRAM, 0);if (sock < 0){std::cerr << "socket error" << std::endl;exit(2);}//client要不要bind?要bind,但是client不会显示的bind,程序员不会自己bind//client是一个客户端,是普通人下载并使用的//如果需要显示的bind,也就要求了客户端也bind了一个固定的端口//万一其他的客户端提前真用了端口号了呢,这时这个客户端就无法启动了//所以不用显示的bind指定端口号,直接让OS自动随机选择std::string message;//给谁发的信息如下struct sockaddr_in server;memset(&server,0,sizeof(server));server.sin_family=AF_INET;server.sin_port=htons(atoi(argv[2]));server.sin_addr.s_addr=inet_addr(argv[1]);char buffer[1024];while(1){std::cout<<"请输入你的信息# ";std::getline(std::cin,message);if(message=="quit"){break;}//当client首次发送消息给服务器的时候,OS会自动给client bind它的ip和portsendto(sock,message.c_str(),message.size(),0,(struct sockaddr*)&server,sizeof(server));//至此客户端和服务器已经建成//这里需要定义两个占位的struct sockaddr_in temp;socklen_t len = sizeof(temp);ssize_t s= recvfrom(sock,&buffer,sizeof(buffer)-1,0,(struct sockaddr*)&temp,&len);if(s>0){buffer[s]=0;std::cout<<"server echo# "<<buffer<<std::endl;}}close(sock);return 0;
}

4.log.hpp

#pragma once#include <iostream>
#include <cstdio>
#include <cstdarg>
#include <ctime>
#include <string>// 日志是有日志级别的
#define DEBUG   0
#define NORMAL  1
#define WARNING 2
#define ERROR   3
#define FATAL   4const char *gLevelMap[] = {"DEBUG","NORMAL","WARNING","ERROR","FATAL"
};#define LOGFILE "./threadpool.log"// 完整的日志功能,至少: 日志等级 时间 支持用户自定义(日志内容, 文件行,文件名)
void logMessage(int level, const char *format, ...)
{
#ifndef DEBUG_SHOWif(level== DEBUG) return;
#endif// va_list ap;// va_start(ap, format);// while()// int x = va_arg(ap, int);// va_end(ap); //ap=nullptrchar stdBuffer[1024]; //标准部分time_t timestamp = time(nullptr);// struct tm *localtime = localtime(&timestamp);snprintf(stdBuffer, sizeof stdBuffer, "[%s] [%ld] ", gLevelMap[level], timestamp);char logBuffer[1024]; //自定义部分va_list args;va_start(args, format);// vprintf(format, args);vsnprintf(logBuffer, sizeof logBuffer, format, args);va_end(args);//FILE *fp = fopen(LOGFILE, "a");printf("%s%s\n", stdBuffer, logBuffer);//fprintf(fp, "%s%s\n", stdBuffer, logBuffer);//fclose(fp);
}

5.结果 

这个叫做本地环回:client和server发送数据只在本地协议栈中进行数据流动,不会把我们的数据发送到网络中,通常用于本地网络服务器的测试

 ——————————————————————————————————————————

其中客户端时OS随机绑定的,全0IP是因为只要是这个端口的我都要,不要具体IP的

三、爆改多线程

我们要把这个代码改成一个类似QQ群一样的模式,所有人发的消息都可以看到

1.udp_client.cc

#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <memory>
#include "thread.hpp"uint16_t serverport=0;
std::string serverip;//发现:无论是多线程读还是写,用的sock都是一个,sock代表就是文件,UDP是全双工的-> 可以同时进行收发而不受干扰static void usage(std::string proc)
{std::cout << "\nUsage: " << proc << " serverIp serverPort\n"<< std::endl;
}//发送逻辑的回调
static void *udpSend(void *args)
{//根据线程的封装,先转换成data*的然后获取里面的args_,然后在转会int*//获得一个指针指向args里面的sock,然后解引用int sock=*(int*)((ThreadData*)args)->args_;std::string name = ((ThreadData*)args)->name_;//下面逻辑与之前一样,构建发送的字符串,套接字信息std::string message;//给谁发的信息如下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(1){std::cerr<<"请输入你的信息# ";std::getline(std::cin,message);if(message=="quit"){break;}//当client首次发送消息给服务器的时候,OS会自动给client bind它的ip和portsendto(sock,message.c_str(),message.size(),0,(struct sockaddr*)&server,sizeof(server));//至此客户端和服务器已经建成}return nullptr;
}//接受逻辑的回调
static void *udpRecv(void *args)
{int sock=*(int*)((ThreadData*)args)->args_;std::string name = ((ThreadData*)args)->name_;//需要不断地去读,要去指定的套接字中读取while(1){char buffer[1024];struct sockaddr_in temp;socklen_t len = sizeof(temp);ssize_t s= recvfrom(sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&temp,&len);if(s>0){buffer[s]=0;std::cout<<buffer<<std::endl;}}
}int main(int argc, char *argv[])
{if (argc != 3){usage(argv[0]);exit(1);}int sock = socket(AF_INET, SOCK_DGRAM, 0);if (sock < 0){std::cerr << "socket error" << std::endl;exit(2);}serverport=atoi(argv[2]);serverip=argv[1];//client要不要bind?要bind,但是client不会显示的bind,程序员不会自己bind//client是一个客户端,是普通人下载并使用的//如果需要显示的bind,也就要求了客户端也bind了一个固定的端口//万一其他的客户端提前真用了端口号了呢,这时这个客户端就无法启动了//所以不用显示的bind指定端口号,直接让OS自动随机选择//爆改多线程,一个线程发送数据到各个主机,一个线程接受各个数据。std::unique_ptr<Thread> sender(new Thread(1,udpSend,(void*)&sock));std::unique_ptr<Thread> recver(new Thread(2,udpRecv,(void*)&sock));sender->start();recver->start();sender->join();recver->join();close(sock);// std::string message;// //给谁发的信息如下// struct sockaddr_in server;// memset(&server,0,sizeof(server));// server.sin_family=AF_INET;// server.sin_port=htons(atoi(argv[2]));// server.sin_addr.s_addr=inet_addr(argv[1]);// char buffer[1024];// while(1)// {//     std::cout<<"请输入你的信息# ";//     std::getline(std::cin,message);//     if(message=="quit")//     {//         break;//     }//     //当client首次发送消息给服务器的时候,OS会自动给client bind它的ip和port//     sendto(sock,message.c_str(),message.size(),0,(struct sockaddr*)&server,sizeof(server));//     //至此客户端和服务器已经建成//     //这里需要定义两个占位的//     struct sockaddr_in temp;//     socklen_t len = sizeof(temp);//     ssize_t s= recvfrom(sock,&buffer,sizeof(buffer)-1,0,(struct sockaddr*)&temp,&len);//     if(s>0)//     {//         buffer[s]=0;//         std::cout<<"server echo# "<<buffer<<std::endl;//     }// }// close(sock);return 0;
}

2.udp_server.cc

#include "udp_server.hpp"
#include <memory>
#include <cstdlib>static void usage(std::string proc)
{std::cout << "\nUsage: " << proc << " port\n" << std::endl;
}int main(int argc,char *argv[])
{//检查传入ip和端口号是否错误if(argc!=2){usage(argv[0]);exit(1);}//初始化服务器,利用unique_ptruint16_t port=atoi(argv[1]);//std::string ip=argv[1];std::unique_ptr<UDPServer> svr(new UDPServer(port));svr->initServer();svr->strat();return 0;
}

3.udp_server.hpp

#ifndef _UDP_SERVER_HPP
#define _UDP_SERVER_HPP#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include "log.hpp"
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <cstdio>
#include <unistd.h>
#include <unordered_map>#define SIZE 1024class UDPServer
{
public:UDPServer(uint16_t port, std::string ip = ""): port_(port), ip_(ip), sock_(-1){}bool initServer(){// 这里开始使用网络部分// 1.创建套接字sock_ = socket(AF_INET, SOCK_DGRAM, 0);if (sock_ < 0){logMessage(FATAL, "%d:%s", errno, strerror(errno));exit(2);}// 2.bind绑定:将用户设置的ip和端口号在内核中和我们的进程强关联//"192.168.1.0"->点分十进制// 以.来分隔,每个区域的取值范围为0——255,// 正好为1字节,四个区域理论上需要四字节// 所以我们的看的时候会由4字节显示,转换为点分十进制// 初始化结构体完成struct sockaddr_in local;bzero(&local, sizeof(local));// 填充结构体local.sin_family = AF_INET;// 服务器的IP和端口号,未来也是要发送给对方主机才能互相通信的// 所以要先把数据发送到网络,要用htonslocal.sin_port = htons(port_);// 同上要先把点分十进制转换成四字节ip// 还需要要把四字节主机序列,转换成网络序列// 所以用inet_addr一次性转成网络四字节序列// local.sin_addr.s_addr=inet_addr(ip_.c_str());// 一般情况下,只要是这个端口的,那么我们就直接全部都接受,而不是指定端口local.sin_addr.s_addr = ip_.empty() ? INADDR_ANY : inet_addr(ip_.c_str());// 这里需要做强转,因为bind需要的是sockaddr类型而不是sockaddr_in类型if (bind(sock_, (struct sockaddr *)&local, sizeof(local)) < 0){logMessage(FATAL, "%d:%s", errno, strerror(errno));exit(2);}// 至此初始化服务器写完,首先创建套接字,接着用bind来绑定ip和端口号写进内核中logMessage(NORMAL, "init udp server done ... %s", strerror(errno));return true;}void strat(){// 作为一款网络服务器,是永远不退出的!//  服务器启动-> 进程 -> 常驻进程 -> 永远在内存中存在,除非挂了!// echo服务器,主机给我们发送消息,我们原封不动的返回char buffer[SIZE];for (;;){// 1.读取数据// 注意peer,纯输出型参数struct sockaddr_in peer;bzero(&peer, sizeof(peer));// 输入:peer 缓冲区大小// 输入:实际读到的peer大小// 所以len的大小要为实际的peer大小socklen_t len = sizeof(peer);// 这样就把数据读取到buffer里了ssize_t s = recvfrom(sock_, &buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);char result[256];char key[64];std::string cmd_echo;if (s > 0){buffer[s] = 0; // 我们目前数据当作字符串// 1.输出发送的数据信息// 2.是谁?提取!// if(strcasestr(buffer,"rm")!=nullptr||strcasestr(buffer,"rmdir")!=nullptr)// {//     std::string err_message="坏人";//     std::cout<<err_message<<buffer<<std::endl;//     sendto(sock_, err_message.c_str(), err_message.size(), 0, (struct sockaddr *)&peer, len);//     continue;// }// FILE *fp = popen(buffer, "r");// if (nullptr == fp)// {//     logMessage(ERROR, "%d:%s", errno, strerror(errno));//     continue;// }// while (fgets(result, sizeof(result), fp) != nullptr)// {//     cmd_echo += result;// }// fclose(fp);uint16_t cil_port = ntohs(peer.sin_port);     // 从网络中来的,所以要进行转成主机端口号std::string cil_ip = inet_ntoa(peer.sin_addr); // 将点分四字节转换成点分十进制,并且将网络序列转换成主机序列// printf("[%s:%d]# %s\n",cli_p.c_str(),cil_port,buffer);snprintf(key, sizeof(key), "%s-%d", cil_ip.c_str(), cil_port);logMessage(NORMAL,"key: %s",key);auto it = users_.find(key);if(it==users_.end()){logMessage(NORMAL,"add new user:%s",key);users_.insert({key,peer});}}// 2.分析和处理数据// 3.写回数据// sendto(sock_,buffer,sizeof(buffer),0,(struct sockaddr*)&peer,len);//sendto(sock_, cmd_echo.c_str(), cmd_echo.size(), 0, (struct sockaddr *)&peer, len);for(auto &iter:users_){std::string sendMessage=key;sendMessage+="# ";sendMessage+=buffer;logMessage(NORMAL,"push message to %s",iter.first.c_str());sendto(sock_, sendMessage.c_str(), sendMessage.size(), 0, (struct sockaddr *)&(iter.second), sizeof(iter.second));}}}~UDPServer(){if (sock_ >= 0){close(sock_);}}private:uint16_t port_;std::string ip_;int sock_;std::unordered_map<std::string, struct sockaddr_in> users_;
};#endif

 4.thread.hpp

#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <cstdio>using namespace std;typedef void*(*fun_t)(void*);class ThreadData
{
public:void* args_;string name_;
};class Thread
{
public:Thread(int num,fun_t callback,void* args):func_(callback){char namebuffer[64];snprintf(namebuffer,sizeof(namebuffer),"Thread-%d",num);name_=namebuffer;tdata_.args_=args;tdata_.name_=name_;}void start(){pthread_create(&tid_,nullptr,func_,&tdata_.args_);}void join(){pthread_join(tid_,nullptr);}string name(){return name_;}~Thread(){}private:string name_;fun_t func_;ThreadData tdata_;pthread_t tid_;
};

5.结果

利用管道可以更好的观看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/526766.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Stable diffusion(一)

Stable diffusion 原理解读 名词解释 正向扩散&#xff08;Fixed Forward Diffusion Process&#xff09;&#xff1a;反向扩散&#xff08;Generative Reverse Denoising Process&#xff09; VAE&#xff08;Variational AutoEncoder&#xff09;&#xff1a;一个用于压缩图…

快速上手:使用Hexo搭建并自定义个人博客

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

再探再报 除 0 这件事有不同

首先&#xff0c;在数学中&#xff0c;一个数除以0是没有意义的。 其次&#xff0c;在计算机中&#xff0c;对于除零&#xff0c;传统概念里是会上报一个异常。首先是CPU内部实现会报异常。最早学组成原理和汇编的时候&#xff0c;都是说CPU寄存器中有个表示除零异常的位。在L…

上位机图像处理和嵌入式模块部署(qmacvisual二维码识别)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 如果说条形码在商品上使用比较多的话&#xff0c;那么二维码识别是一个更加使用频繁的场合。为什么使用这样频繁&#xff0c;我想很多一部分原因来…

渗透测试——信息收集

信息收集 前言 信息收集是在做渗透时找尽可能的多的信息&#xff0c;为之后的渗透做铺垫。信息收集的方法有很多 比如&#xff0c;页面、真实的IP、域名/子域名、敏感目录/文件、端口探测、CMS指纹识别、操作系统识别 1. 页面信息收集 拿到域名后&#xff0c;从网站的url中…

Bee Mobile组件库重磅升级

Bee Mobile组件库重磅升级&#xff01; 丰富强大的组件移动预览快速上手create-bee-mobile Bee Mobile组件库重磅升级&#xff01; Bee Mobile组件库最新 v1.0.0 版本&#xff0c;支持最新的 React v18。 主页&#xff1a;Bee Mobile 丰富强大的组件 一共拥有50多个组件&…

基于javaweb+springboot开发的城市地名地址信息管理系统设计和实现

基于javaweb(springboot)城市地名地址信息管理系统设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言…

一切都在变好

&#xff08;1&#xff09;规模复杂性Hold不住了 我已经说过多次&#xff0c;有几个&#xff1a; 1、5400多只股票&#xff0c;还会再持续增加 2、2.2亿账户&#xff0c;每年还以1600万在增加 3、60-90万亿市值 4、每天6000亿-万亿交易额&#xff0c;看趋势还在增加 也就是说&a…

时间序列-AR MA ARIMA

一、AR模型(自回归) AR探索趋势和周期性 预测依赖于过去的观测值和模型中的参数。模型的阶数 p pp 决定了需要考虑多少个过去时间点的观测值。 求AR模型的阶数 p和参数 ϕ i \phi_i ϕi​ &#xff0c;常常会使用统计方法如最小二乘法、信息准则&#xff08;如AIC、BIC&#xf…

开源的Java图片处理库介绍

在 Java 生态系统中&#xff0c;有几个流行的开源库可以用于图片处理。这些库提供了丰富的功能&#xff0c;如图像缩放、裁剪、颜色调整、格式转换等。以下是几个常用的 Java 图片处理库的介绍&#xff0c;包括它们的核心类、主要作用和应用场景&#xff0c;以及一些简单的例子…

加密流量分类torch实践4:TrafficClassificationPandemonium项目更新

加密流量分类torch实践4&#xff1a;TrafficClassificationPandemonium项目更新 更新日志 3/10号更新 流量预处理更新 增加了基于splitCap.exe分流预处理&#xff0c;并且除了提取负载与包长序列后&#xff0c;支持提取统计特征&#xff08;26维度&#xff09;。 26维度统计…

表单进阶(3)-上传文件和隐藏字段

上传文件&#xff1a;<input type"file"> 隐藏字段&#xff1a;<input type"hidden" name"" id"" value"带给后端的信息"> 禁用disabled&#xff1a;<button disabled"disabled">注册</bu…