【教你抢课】C++网络编程之使用Winsock2实现教务系统自动抢课程序

news/2024/11/16 17:58:29/

 

一、开发环境及工具:

· Microsoft Visual Studio(本程序使用的是Microsoft Visual Studio 2012)

 

· Chrome浏览器(其他浏览器也可以)

 

二、原理及实现:

1.原理概述:

用浏览器登录教务系统,实际上是Request了一个POST请求。

而在浏览器的选课界面中,点击“选课”按钮,则相当于向对方服务器Request了一个GET请求。

本程序使用C++编程语言,利用Windows网络编程接口Winsock2模拟浏览器的Request操作,

不断地将请求发送至对方服务器,当有人抛课时,实现自动抢课。

 

2.浏览器登录及点击的工作原理。

我们用浏览器打开一个新的标签页,按F12进入开发者工具的Network选项,在地址栏中输入教务系统网站,进入教务系统登录界面。

表面上看,我们输入教务系统的网址并跳转,浏览器就给出这个网址的界面了。

细节上,则是客户机(我们的电脑)给对方服务器(教务系统的服务器)提交了一个GET的请求。

(具体请求信息保存在Request Headers里面并发送给对方,包括对方服务器主机名、浏览器版本、cookie等信息)

对方服务器收到我们的请求,于是响应这一请求,也用一个Request Headers的方式发给我们,并为我们的请求提供服务

(例如网页界面的HTML代码、图片等)。

 

利用F12开发者工具的Network选项查看Request和Response的具体信息:

 

接下来,我们填写上用户名、密码及验证码。

如果用户名、密码和验证码均输入无误,点击“登录”按钮后,则可成功登录进入学生个人中心,如下图。

我们一开始在浏览器中输入网址后跳转,请求方式为GET,作用是从服务器上获取登陆界面的数据内容。

而这一次,我们提交登录信息的请求类型为POST,作用是向服务器传送数据,包括用户名、密码和验证码等。

以下是这一POST请求以及服务器对这个请求的响应:

 

2.利用Winsock2在程序中模拟上述登录及点击过程

由于本程序要利用模拟浏览器发送请求的原理,程序要获取到这些请求信息,因此我们必须预先完成以下工作:

①.打开浏览器 --> 打开开发者工具 

②.在浏览器中登录一次 --> 记录登录时的request headers(类型为POST)

③.进入一次选课系统  --> 记录打开选课系统时的request headers(类型为GET)

④.点击“选课”按钮选一门要抢的课 --> 记录选这一门课的request headers(类型为GET)

 

a.登录过程中发送的request headers如下:

在代码中创建并初始化一个字符串变量request_login,用于保存以上请求信息,将上述Request Headers的信息原封不动地抄下来:

 

//登录POST请求(Request Headers)
string request_login ="POST /jsxsd/xk/LoginToXkLdap HTTP/1.1\r\n""Host: jxgl.gdufs.edu.cn\r\n""Connection: keep-alive\r\n""Content-Length: 54\r\n"            //账号密码的长度不同,Content-Length的值也不同,登录不同账号时要注意"Cache-Control: max-age=0\r\n""Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n""Origin: http://jxgl.gdufs.edu.cn\r\n""Upgrade-Insecure-Requests: 1\r\n""User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36\r\n""Content-Type: application/x-www-form-urlencoded\r\n""Referer: http://jxgl.gdufs.edu.cn/jsxsd/""\r\n""Accept-Encoding: gzip, deflate\r\n""Accept-Language: zh-CN,zh;q=0.8\r\n""Cookie: _gscu_526019281=882896108k64eh79; JSESSIONID=80E45C39F94A1EC5A40C9D1407FBFE32"     //重启浏览器后,cookie的值要及时更新"\r\n""\r\n""USERNAME=666666"   //填写学号,例如666666"&PASSWORD=999999"  //填写密码,例如999999"&RANDOMCODE=";     //验证码这里先不写,程序运行时再进行字符串拼接

b.进入选课界面,把选课界面的Request Headers抄下来(如果是新开一个弹窗,刷新一下即可),用一个string变量保存:

 

 

//进入选课界面的GET请求信息(Request Headers)
string request_choose_course ="GET /jsxsd/xsxk/xsxk_index?jx0502zbid=0B2F353D2507431F9D45F18AA941AFE0 HTTP/1.1\r\n"    "Host: jxgl.gdufs.edu.cn\r\n""Connection: keep-alive\r\n""Cache-Control: max-age=0\r\n""Upgrade-Insecure-Requests: 1\r\n""User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36\r\n""Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n""Referer: http://jxgl.gdufs.edu.cn/jsxsd/xsxk/xklc_list?Ves632DSdyV=NEW_XSD_PYGL""\r\n""Accept-Encoding: gzip, deflate, sdch\r\n""Accept-Language: zh-CN,zh;q=0.8\r\n""Cookie: _gscu_526019281=882896108k64eh79; JSESSIONID=80E45C39F94A1EC5A40C9D1407FBFE32"      //重启浏览器后,cookie的值要及时更新"\r\n";

c.在选修选课界面,找到我们需要抢的课(这里以编译原理为例),点击“选课”按钮:

 

同理,新建一个string变量,保存刚刚点击编译原理“选课”按钮后,提交的Request Headers:

 

//点击编译原理“选课”按钮的GET请求信息(Request Headers)
string request_compilers_principles ="GET /jsxsd/xsxkkc/xxxkOper?jx0404id=201620172009027 HTTP/1.1\r\n"    //每门课的jx0404id都不同,编译原理这门课对应的是201620172009027 "Host: jxgl.gdufs.edu.cn\r\n""Connection: keep-alive\r\n""Accept: */*\r\n""X-Requested-With: XMLHttpRequest\r\n""User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36\r\n""Referer: http://jxgl.gdufs.edu.cn/jsxsd/xsxkkc/comeInXxxk""\r\n""Accept-Encoding: gzip, deflate, sdch\r\n""Accept-Language: zh-CN,zh;q=0.8\r\n""Cookie: _gscu_526019281=882896108k64eh79; JSESSIONID=80E45C39F94A1EC5A40C9D1407FBFE32"       //重启浏览器后,cookie的值要及时更新"\r\n";

 

 

 

 

 

这样一来,上述的三个Request Headers已经保存好了,下面开始用程序模拟登录及进入选课系统。

以下代码用于启动Winsock,创建socket,实现模拟登陆以及模拟进入选课界面:

 

	/*启动Winsock*/WSADATA wd;WSAStartup(MAKEWORD(2, 2), &wd);     //SOCKET temp = socket(AF_INET, SOCK_STREAM, 0);  /*创建socket*/sock = socket(AF_INET, SOCK_STREAM, 0);  if (sock == INVALID_SOCKET){cout << "建立socket失败! 错误码: " << WSAGetLastError() << endl;return;}/*绑定:将本地地址 附加到 套接字上 以便能够有效地标识套接字*/sockaddr_in sa = { AF_INET };    //套接字地址,AF _!NET ,表示该socket位于Internet域;int n = bind(sock, (sockaddr*)&sa, sizeof(sa));if (n == SOCKET_ERROR){cout << "绑定失败! 错误码: " << WSAGetLastError() << endl;return;}struct hostent *p = gethostbyname(host);if (p == NULL){cout << "主机无法解析出ip! 错误代码: " << WSAGetLastError() << endl;return;}sa.sin_port = htons(80);memcpy(&sa.sin_addr, p->h_addr, 4);//   with some problems ???/*连接:当客户机要与网络中的服务器建立连接时,需要调用connect 函数*/n = connect(sock, (sockaddr*)&sa, sizeof(sa));if (n == SOCKET_ERROR)	{cout << "连接失败! 错误码: " << WSAGetLastError() << endl;return;}if (isLogin == false){/*登录教务系统*/if(isCookie == false){isCookie = true;}string verification_code = "";                    //验证码cout<<"请输入验证码: ";cin>>verification_code;string request_login_full = request_login + verification_code;cout<<"开始将登录请求(Request Headers)发送至对方服务器..."<<endl;if (send(sock, request_login_full.c_str(), request_login_full.size(), 0) == SOCKET_ERROR){cout << "发送失败! 错误代码: " << WSAGetLastError() << endl;closesocket(sock);return;}else{cout<<"发送成功!"<<endl;}if(recv(sock, buf, sizeof(buf)-1, 0) > 0){cout<<"以下是服务器的响应信息(Response Headers)"<<endl;printf("%s",buf);cout<<endl;}/*进入选课系统*/cout<<"开始将进入选课界面的请求信息(Request Headers)发送至对方服务器..."<<endl;if (send(sock, request_choose_course.c_str(), request_choose_course.size(), 0) == SOCKET_ERROR){cout << "发送失败! 错误代码: " << WSAGetLastError() << endl;closesocket(sock);return;}else{cout<<"发送成功!"<<endl;}if(recv(sock, buf, sizeof(buf)-1, 0) > 0){cout<<endl<<"以下是服务器的响应信息(Response Headers)"<<endl;printf("%s",buf);cout<<endl;}system("pause");isLogin = true;}

用刚刚的浏览器打开教务系统登陆界面,运行这段代码,并输入浏览器中显示的验证码:

 

输入验证码完毕,点击Enter,程序输出登录请求和选课请求的响应情况:

观察程序输出的登录请求和选课请求的响应情况,发现和之前浏览器的两次响应情况相吻合(除了响应时间Date)。

这说明本次程序登陆成功:

登录请求的Response Headers,和控制台的响应信息相吻合

 

进入选课界面请求的Response Headers,和控制台的响应信息相吻合

 

这时候,我们可以试试在浏览器中输入上面蓝色方框的地址,也就是登陆成功后重定向跳转后的地址。

我们会发现,即使没有在浏览器没有填写用户名、密码等登录信息,我们也可以直接进入学生个人中心:

这是因为我们的程序已经成功模拟了浏览器的登录过程。

 

3.利用循环语句模拟点击“选课”按钮实现自动抢课

 

//开始抢课init_sec = time(0);   //计时开始int count_num = 0;/*循环抢课*/while (true){//每一次都重新建立连接SOCKET temp = socket(AF_INET, SOCK_STREAM, 0);  sock = temp;if (sock == INVALID_SOCKET){cout << "建立socket失败! 错误代码: " << WSAGetLastError() << endl;return;}sockaddr_in sa = { AF_INET };   struct hostent *p = gethostbyname(host);if (p == NULL){cout << "主机无法解析出ip! 错误代码: " << WSAGetLastError() << endl;return;}sa.sin_port = htons(80);memcpy(&sa.sin_addr, p->h_addr, 4);/*连接:当客户机要与网络中的服务器建立连接时,需要调用connect 函数*/n = connect(sock, (sockaddr*)&sa, sizeof(sa));if (n == SOCKET_ERROR)	{cout << "连接失败! 错误代码: " << WSAGetLastError() << endl;return;}count_num++;tot_sec = time(0) - init_sec;tot_sec_main = time(0) - main_time;//抢课:编译原理cout<<"开始将编译原理选课请求(Request Headers)发送至对方服务器..."<<endl;if (send(sock, request_compilers_principles.c_str(), request_compilers_principles.size(), 0) == SOCKET_ERROR){cout << "发送失败! 错误代码: " << WSAGetLastError() << endl;grabCourse();  //递归return;}else{cout<<"发送成功"<<endl;}if(count_num % ignoreTimes == 0){if(recv(sock, recv_buf, sizeof(recv_buf)-1, 0) > 0){cout<<endl<<"以下是服务器的响应信息(Response Headers)"<<endl;printf("%s",recv_buf);}}cout<<"程序运行总计时长(单位:秒):"<<tot_sec_main<<endl;cout<<"本次循环时长(单位:秒):"<<tot_sec<<endl;cout<<"执行次数:"<<count_num<<endl;cout<<"平均每秒执行次数:"<<(double)count_num/tot_sec<<endl;closesocket(temp);}

4.代码说明:

 

①.每一次循环都重新新建了一个名为temp的临时socket实例,用于避免错误代码10054。

产生错误代码10054的原因:现有连接被远程主机强制关闭。

解决办法:每一次循环都重新生成一个新的socket实例,无论上次连接成功与否,每一次都重新建立一次连接。

②.每一次循环结束前,调用closesocket()函数及时释放socket对象,以免系统资源耗尽。

③.点击“选课”按钮时,不同课的Request Headers的唯一不同点就是jx0404id,例如编译原理这门课对应的是jx0404id=201620172009027。如果要抢多门课,只需修改jx0404id,其余的Request Headers信息直接复制即可。

④.控制台输出乱码情况有待解决。

 

5.注意:

①.如果浏览器重启,或者电脑重启后,所有的Request Headers中的cookie信息都要重新输入。

②.在登录请求的Request Headers中,不同用户账号密码的长度不同,Content-Length的值也不同,不同账号登录时要注意。

 

6.本程序完整代码及运行截图:

 

#include <iostream>
#include <cstring>
#include<ctime>
#include <winsock2.h>
#include <Windows.h>
#include <string>
#define max 20480using namespace std;
#pragma comment(lib, "ws2_32.lib")//全局变量
char host[500]="jxgl.gdufs.edu.cn";
char buf[1024];int num = 1;
string allHtml;int ignoreTimes = 1000;     //设置消息接收频率,目前默认每发送1000次接受一次
SOCKET sock;bool isLogin = false;
bool isCookie = false;int main_time;
int init_sec;     //计时开始的初始时间 
int tot_sec;     //耗时
int tot_sec_main;     //耗时char recv_buf[1024];//登录请求(Request Headers)
string request_login ="POST /jsxsd/xk/LoginToXkLdap HTTP/1.1\r\n""Host: jxgl.gdufs.edu.cn\r\n""Connection: keep-alive\r\n""Content-Length: 54\r\n""Cache-Control: max-age=0\r\n""Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n""Origin: http://jxgl.gdufs.edu.cn\r\n""Upgrade-Insecure-Requests: 1\r\n""User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36\r\n""Content-Type: application/x-www-form-urlencoded\r\n""Referer: http://jxgl.gdufs.edu.cn/jsxsd/""\r\n""Accept-Encoding: gzip, deflate\r\n""Accept-Language: zh-CN,zh;q=0.8\r\n""Cookie: _gscu_526019281=882896108k64eh79; JSESSIONID=80E45C39F94A1EC5A40C9D1407FBFE32""\r\n""\r\n""USERNAME=666666"   //填写学号,例如666666"&PASSWORD=999999"  //填写密码,例如999999"&RANDOMCODE=";//进入选课界面的请求信息(Request Headers)
string request_choose_course ="GET /jsxsd/xsxk/xsxk_index?jx0502zbid=0B2F353D2507431F9D45F18AA941AFE0 HTTP/1.1\r\n""Host: jxgl.gdufs.edu.cn\r\n""Connection: keep-alive\r\n""Cache-Control: max-age=0\r\n""Upgrade-Insecure-Requests: 1\r\n""User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36\r\n""Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n""Referer: http://jxgl.gdufs.edu.cn/jsxsd/xsxk/xklc_list?Ves632DSdyV=NEW_XSD_PYGL""\r\n""Accept-Encoding: gzip, deflate, sdch\r\n""Accept-Language: zh-CN,zh;q=0.8\r\n""Cookie: _gscu_526019281=882896108k64eh79; JSESSIONID=80E45C39F94A1EC5A40C9D1407FBFE32""\r\n";//要抢的课:编译原理
string request_compilers_principles ="GET /jsxsd/xsxkkc/xxxkOper?jx0404id=201620172009027 HTTP/1.1\r\n""Host: jxgl.gdufs.edu.cn\r\n""Connection: keep-alive\r\n""Accept: */*\r\n""X-Requested-With: XMLHttpRequest\r\n""User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36\r\n""Referer: http://jxgl.gdufs.edu.cn/jsxsd/xsxkkc/comeInXxxk""\r\n""Accept-Encoding: gzip, deflate, sdch\r\n""Accept-Language: zh-CN,zh;q=0.8\r\n""Cookie: _gscu_526019281=882896108k64eh79; JSESSIONID=80E45C39F94A1EC5A40C9D1407FBFE32""\r\n";//抢课
void grabCourse(){/*启动Winsock*/WSADATA wd;WSAStartup(MAKEWORD(2, 2), &wd);     //SOCKET temp = socket(AF_INET, SOCK_STREAM, 0);  /*创建socket*/sock = socket(AF_INET, SOCK_STREAM, 0);  if (sock == INVALID_SOCKET){cout << "建立socket失败! 错误码: " << WSAGetLastError() << endl;return;}/*绑定:将本地地址 附加到 套接字上 以便能够有效地标识套接字*/sockaddr_in sa = { AF_INET };    //套接字地址,AF _!NET ,表示该socket位于Internet域;int n = bind(sock, (sockaddr*)&sa, sizeof(sa));if (n == SOCKET_ERROR){cout << "绑定失败! 错误码: " << WSAGetLastError() << endl;return;}struct hostent *p = gethostbyname(host);if (p == NULL){cout << "主机无法解析出ip! 错误代码: " << WSAGetLastError() << endl;return;}sa.sin_port = htons(80);memcpy(&sa.sin_addr, p->h_addr, 4);//   with some problems ???/*连接:当客户机要与网络中的服务器建立连接时,需要调用connect 函数*/n = connect(sock, (sockaddr*)&sa, sizeof(sa));if (n == SOCKET_ERROR)	{cout << "连接失败! 错误码: " << WSAGetLastError() << endl;return;}if (isLogin == false){/*登录教务系统*/if(isCookie == false){isCookie = true;}string verification_code = "";                    //验证码cout<<"请输入验证码: ";cin>>verification_code;string request_login_full = request_login + verification_code;cout<<"开始将登录请求(Request Headers)发送至对方服务器..."<<endl;if (send(sock, request_login_full.c_str(), request_login_full.size(), 0) == SOCKET_ERROR){cout << "发送失败! 错误代码: " << WSAGetLastError() << endl;closesocket(sock);return;}else{cout<<"发送成功!"<<endl;}if(recv(sock, buf, sizeof(buf)-1, 0) > 0){cout<<"以下是服务器的响应信息(Response Headers)"<<endl;printf("%s",buf);cout<<endl;}/*进入选课系统*/cout<<"开始将进入选课界面的请求信息(Request Headers)发送至对方服务器..."<<endl;if (send(sock, request_choose_course.c_str(), request_choose_course.size(), 0) == SOCKET_ERROR){cout << "发送失败! 错误代码: " << WSAGetLastError() << endl;closesocket(sock);return;}else{cout<<"发送成功!"<<endl;}if(recv(sock, buf, sizeof(buf)-1, 0) > 0){cout<<endl<<"以下是服务器的响应信息(Response Headers)"<<endl;printf("%s",buf);cout<<endl;}system("pause");isLogin = true;}//开始抢课init_sec = time(0);   //计时开始int count_num = 0;/*循环抢课*/while (true){//每一次都重新建立连接SOCKET temp = socket(AF_INET, SOCK_STREAM, 0);  sock = temp;if (sock == INVALID_SOCKET){cout << "建立socket失败! 错误代码: " << WSAGetLastError() << endl;return;}sockaddr_in sa = { AF_INET };   struct hostent *p = gethostbyname(host);if (p == NULL){cout << "主机无法解析出ip! 错误代码: " << WSAGetLastError() << endl;return;}sa.sin_port = htons(80);memcpy(&sa.sin_addr, p->h_addr, 4);/*连接:当客户机要与网络中的服务器建立连接时,需要调用connect 函数*/n = connect(sock, (sockaddr*)&sa, sizeof(sa));if (n == SOCKET_ERROR)	{cout << "连接失败! 错误代码: " << WSAGetLastError() << endl;return;}count_num++;tot_sec = time(0) - init_sec;tot_sec_main = time(0) - main_time;//抢课:编译原理cout<<"开始将编译原理选课请求(Request Headers)发送至对方服务器..."<<endl;if (send(sock, request_compilers_principles.c_str(), request_compilers_principles.size(), 0) == SOCKET_ERROR){cout << "发送失败! 错误代码: " << WSAGetLastError() << endl;grabCourse();  //递归return;}else{cout<<"发送成功"<<endl;}if(count_num % ignoreTimes == 0){if(recv(sock, recv_buf, sizeof(recv_buf)-1, 0) > 0){cout<<endl<<"以下是服务器的响应信息(Response Headers)"<<endl;printf("%s",recv_buf);}}cout<<"程序运行总计时长(单位:秒):"<<tot_sec_main<<endl;cout<<"本次循环时长(单位:秒):"<<tot_sec<<endl;cout<<"执行次数:"<<count_num<<endl;cout<<"平均每秒执行次数:"<<(double)count_num/tot_sec<<endl;closesocket(temp);}
}int main(){main_time = time(0);  //开始计时grabCourse();system("pause");return 0;
}

 

 

 

 

 

程序完整运行情况如下图:

 

7.提速小Tips

ignoreTimes对应消息接收的频繁程度,将ignoreTimes的值设为1000,表示每发送1000次请求,才接受一次响应消息。

如下图所示,将ignoreTimes的值调高,可以显著提高每秒执行次数。

毕竟发送一次就马上接收一次,肯定不够发送千次才接收一次运行的快。

 

 

 

 


http://www.ppmy.cn/news/363509.html

相关文章

远程控制软件哪家好?六款主流远控软件全方位测评

*本文内容以及测试数据来自“B站” 作者&#xff1a;小李student 什么是远控软件?选择远控软件的标准又是什么呢?今天我将测评6款主流的软件来帮大家看看谁是最强远控软件!本次参与测试的远程软件有向日葵、todesk、RayLink、win10自带的远程助手(快速助手)、team viewer、以…

可用QQ远程操控的ESP32的智能家居控制系统

可用QQ远程操控的ESP32的智能家居控制系统 Based on M5GO(chip: ESP32). The communication system is powered by QQbot. GitHub 本项目采用的设备是M5GO&#xff08;esp32芯片&#xff09;&#xff0c;采用MQTT方式与服务器通信。借助Mirai QQ机器人框架&#xff0c;实现QQ远…

关于c++ extern关键字

解释和说明参考&#xff1a; (227条消息) C extern关键字_Candyerer的博客-CSDN博客 (227条消息) 对于C中的extern关键字用法的理解_c extern_Fanfan21ya的博客-CSDN博客 个人写了一个案例&#xff0c;代码结构如下 在总结一下 1.a.cpp文件需要引用b.cpp的文件中的变量或…

智能录音笔完成全系列布局,科大讯飞还发了一款转写翻译智能耳机

作者 | Just 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 9月1日&#xff0c;科大讯飞在其消费类新品发布会一连发布四款硬件新品&#xff1a;智能录音笔SR901、SR702、SR101&#xff0c;以及首款智能TWS耳机iFLYBUDS。 一上台&#xff0c;科大讯飞轮值总裁胡郁…

【xtku】善用智能语音控制电脑

作为新一代人类&#xff0c;这懒人还真的是越来越多&#xff0c;能多懒就多懒&#xff0c;今日小编无意中发现了Win7作为微软新一代操作系统&#xff0c;不仅有炫酷的桌面设计&#xff0c;也有新颖便利的功能&#xff0c;当然也有更智能化的功能设计&#xff0c;其中&#xff0…

基于蓝牙智能家庭影音控制系统---粤嵌GEC6818嵌入式系统实训

版本介绍普通版完整版至尊版 版本介绍 分为普通版、完整版、至尊版三个版本。 普通版 可以满足实训要求&#xff0c;提供代码&#xff0c;不提供技术指导。 实现功能&#xff1a; 1所有界面自行设计&#xff0c;要求尽可能好看 2、执行程序&#xff0c;加载主界面 3、主界面…

Cesium加载影像地图

在Cesium中&#xff0c;加载影像图层主要通过ImageryLayer、ImageryProvider和ImageryLayerCollection三个类来实现&#xff1b;首先我们先来认识下这三个类 一、ImageryLayer类 在Cesium中&#xff0c;使用ImageryLayer对象来表示一个影像图层。ImageryLayer是一个包含一个或…

MM32F3273G8P火龙果开发板MindSDK开发教程16 - 获取msa311加速器的自由落体事件

MM32F3273G8P火龙果开发板MindSDK开发教程16 - 获取msa311加速器的自由落体事件 1、功能描述 类似手环检测老人跌倒的功能&#xff0c;当msa311模块自由落体运动时&#xff0c;可生成中断。 该中断基于加速度数据与低g阈值的比较。通过将1写入位&#xff08;0x17&#xff09;…