0%

Jetbrains fleet 配置 C++开发环境

1. 安装 Jetbrains Fleet

到Fleet下载页面下载Toolbox并安装
Jetbrains-Fleet下载页
安装完成后在任务栏打开 Toolbox ,在列表中选择安装 fleet。

2. 为 Fleet 准备 Workspace

在适当的地方建立文件夹作为 fleet 的工作空间,并在 fleet 中打开。

3. 配置 run.json 编译脚本

点击运行按钮,选择 Create Run Configuration
将其中内容配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{
"configurations": [
{
"type": "command",
"name": "CMake Build",
"program": "cmake",
"args": ["-DCMAKE_BUILD_TYPE=Debug","-G","MinGW Makefiles","-S", "$FILE_DIR$", "-B", "$FILE_DIR$\\cmake-build-debug"],
},
{
"type": "command",
"name": "Make",
"program": "mingw32-make",
"args": ["-C","$FILE_DIR$\\cmake-build-debug"],

},
{
"type": "command",
"name": "Run",
"program": "$FILE_DIR$\\cmake-build-debug\\$FILE_NAME_NO_EXT$.exe",
},
{
"type": "command",
"name": "Build And Run",
"program": "$FILE_DIR$\\cmake-build-debug\\$FILE_NAME_NO_EXT$.exe",
"dependsOn": ["CMake Build", "Make"],
},
{
"type": "command",
"name": "Example Build",
"program": "g++",
"args": ["$FILE$","-o","$FILE_DIR$\\$FILE_NAME_NO_EXT$.exe"]
},
{
"type": "command",
"name": "Example Run",
"program": "$FILE_DIR$\\$FILE_NAME_NO_EXT$.exe",
},
{
"type": "command",
"name": "Example Build And Run",
"program": "$FILE_DIR$\\$FILE_NAME_NO_EXT$.exe",
"dependsOn": ["Example Build"],
},
]
}

4. 安装 CMAKE 与MinGW-w64

CMAKE下载页面
MinGW-w64预编译二进制文件下载页面

CMAKE 直接安装即可,MinGW-w64 找个地方解压出来即可。
之后将 CMAKE 和 MinGW 的 bin 文件夹添加进系统 path 变量。

5. 运行配置如何使用

5.1 单个文件的编译运行

在工作空间下新建项目文件夹,在内部建立单个 cpp 文件并编写程序。
点击运行按钮,其中带 Example 前缀的是用于单个文件运行的配置:

  • Example Build —— 编译该文件
  • Example Run —— 不重新编译,运行上次编译的结果
  • Example Build And Run —— 编译并运行当前文件

5.2 以 CMAKE 管理的项目的编译运行

在工作空间下新建项目文件夹,内部项目以 CMAKE 管理。

  • CMakeLists.txt 中的项目名需要与作为 main 文件的文件名一致,例如主文件为helloworld.cpp,则 CMAKE 中的项目名应为helloworld
  • 如果要使用 fleet 的 Smart Mode,CMakeLists.txt 中需要添加set(CMAKE_EXPORT_COMPILE_COMMANDS ON)生成编译数据库

点击运行按钮,其中不带 Example 前缀的是用于项目运行的配置:

  • CMake Build —— 执行 CMAKE 项目构建,生成项目 Makefile 文件与编译数据库
  • Make —— 编译项目
  • Run —— 不重新编译,运行上次编译的结果
  • Build And Run —— 编译项目并运行

{"created_time":"2022-12-13T12:17:53Z","files":[{"attachment_folder":"","created_time":"2022-12-13T12:17:53Z","id":"3","modified_time":"2022-12-13T12:57:12Z","name":"C-多线程开发.md","signature":"27205993786737","tags":[]},{"attachment_folder":"","created_time":"2022-12-13T12:17:53Z","id":"4","modified_time":"2022-12-13T13:01:21Z","name":"Git简明教程.md","signature":"113818304277873","tags":[]},{"attachment_folder":"","created_time":"2022-12-13T12:17:53Z","id":"5","modified_time":"2022-12-13T12:58:59Z","name":"PC下安卓拆包编译打包与重新签名.md","signature":"82331899030897","tags":[]},{"attachment_folder":"","created_time":"2022-12-13T12:17:53Z","id":"6","modified_time":"2022-12-13T13:00:34Z","name":"Windows11安装教程.md","signature":"67535736696177","tags":[]},{"attachment_folder":"","created_time":"2022-12-13T12:17:54Z","id":"7","modified_time":"2022-12-13T12:17:54Z","name":"更改开机引导LOGO(无需下载BIOS文件).md","signature":"49299305557362","tags":[]},{"attachment_folder":"","created_time":"2022-12-13T12:17:54Z","id":"8","modified_time":"2022-12-13T13:01:01Z","name":"机械键盘选购.md","signature":"126093320809842","tags":[]},{"attachment_folder":"","created_time":"2022-12-13T12:17:54Z","id":"9","modified_time":"2022-12-13T12:54:58Z","name":"漏洞扫描.md","signature":"115802579168626","tags":[]},{"attachment_folder":"","created_time":"2022-12-13T12:17:54Z","id":"10","modified_time":"2022-12-13T13:06:57Z","name":"网络编程(1).md","signature":"105073750863218","tags":[]},{"attachment_folder":"","created_time":"2022-12-13T12:17:54Z","id":"11","modified_time":"2022-12-13T12:17:54Z","name":"计算机协会社课01.md","signature":"24504459357554","tags":[]},{"attachment_folder":"","created_time":"2022-12-13T12:17:54Z","id":"12","modified_time":"2022-12-13T12:17:54Z","name":"计算机协会社课02.md","signature":"120883525479794","tags":[]},{"attachment_folder":"","created_time":"2022-12-26T07:56:52Z","id":"22","modified_time":"2022-12-26T07:59:51Z","name":"网络编程(2).md","signature":"177765700548","tags":[]},{"attachment_folder":"","created_time":"2022-12-26T07:59:24Z","id":"23","modified_time":"2022-12-26T08:00:38Z","name":"网络编程(3)基本服务端实现.md","signature":"79316833096796","tags":[]},{"attachment_folder":"","created_time":"2022-12-26T08:01:18Z","id":"24","modified_time":"2022-12-26T08:01:55Z","name":"网络编程(4)基本客户端实现.md","signature":"27205994894542","tags":[]},{"attachment_folder":"250420816240395","created_time":"2022-12-26T08:08:21Z","id":"25","modified_time":"2022-12-26T08:15:39Z","name":"SublimeText_CPP编译系统.md","signature":"113818305386101","tags":[]},{"attachment_folder":"","created_time":"2022-12-27T07:01:11Z","id":"26","modified_time":"2022-12-28T12:00:18Z","name":"VNote推送HEXO-Task.md","signature":"177765783607","tags":[]},{"attachment_folder":"","created_time":"2022-12-28T11:53:04Z","id":"27","modified_time":"2022-12-28T11:58:23Z","name":"SublimeText_JAVA编译系统.md","signature":"177765887520","tags":[]},{"attachment_folder":"","created_time":"2025-01-06T13:09:43Z","id":"28","modified_time":"2025-01-06T13:54:12Z","name":"jetbrains-fleet配置C++开发环境.md","signature":"11545804367575373335","tags":[]}],"folders":[],"id":"2","modified_time":"2022-12-13T12:17:53Z","signature":"79316831989105","version":3}

新建编译系统,输入以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{      
"cmd" : ["javac", "$file_name"],
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
"selector" : "source.java",
"shell":false,
"working_dir" : "$file_path",
"variants":
[
{
"name": "RunInCommand",
"cmd":
[
"cmd", "/c", "javac","${file}","&&","start", "cmd", "/k", "java $file_name"
]
},
{
"name":"Debug",
"cmd":
[
"cmd", "/c","javac","${file}","&&","start", "cmd", "/k","gdb ${file_path}/${file_base_name}"
]
}
]
}

核心思路:

  1. 成因: VNote的vx.jsonvx_notebook会导致hexo文档管理错误,在博客中产生多个乱码页面(json被误识别为笔记)
  2. vx_notebook处理:选择文件夹作为笔记本的时候选用上一级目录(source文件夹)
  3. vx.json处理:在推送前调用系统命令把vx.json移走,部署完再移回来

简单的参考示例:

1
2
3
{
"command": "move-item D:\\AirLongDianBLOG\\source\\_posts\\vx.json D:\\;hexo d -g --cwd D:\\AirLongDianBLOG\\;move-item D:\\vx.json D:\\AirLongDianBLOG\\source\\_posts\\"
}

(ps:这篇就是拿vnote的task推的)

新建编译系统,输入以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{ 
"cmd" : ["g++", "$file_name", "-o", "${file_base_name}", "-lm", "-Wall"],
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
"selector" : "source.c, source.c++",
"shell":false,
"working_dir" : "$file_path",
"variants":
[
{
"name": "RunInCommand",
"cmd": ["cmd", "/c", "g++","-g", "${file}", "-o", "${file_path}/${file_base_name}", "&&","start", "cmd", "/k", "${file_path}/${file_base_name}"]
}
]
}

基本客户端实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
int main()
{
// make socket
int soct1=socket(AF_INET,SOCK_STREAM,0);
if(soct1 == -1)
{
std::cerr<<"create socket failed!"<<std::endl;
return -1;
}
// init ip address
struct sockaddr_in host;
host.sin_family = AF_INET;
host.sin_port = htons(12345);
host.sin_addr.s_addr = INADDR_ANY;
//connect
int flag=connect(soct1,(sockaddr*)&host,sizeof(sockaddr));
if (flag==-1)
{
std::cerr<<"connect failed"<<std::endl;
return -1;
}
char buffer[1024];
//communicate
while (true)
{
sprintf(buffer,"hello server!");
send(soct1,buffer,strlen(buffer)+1,0);
//reset buffer
memset(buffer,0,sizeof(buffer));
int rec1=recv(soct1,buffer,sizeof(buffer),0);
if (rec1>0)
{
std::cerr<<buffer<<std::endl;
}
else if (rec1=0)
{
std::cerr<<"server disconnect"<<std::endl;
}
else
{
std::cerr<<"send failed"<<std::endl;
}
sleep(1);
}
close(soct1);

}

基本服务端实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <string>
#include <arpa/inet.h>
#include <cstring>
using namespace::std;
int main()
{
// make socket

int soct1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (soct1 == -1)
{
std::cerr<<"create socket fail!"<<std::endl;
return -1;
}

// init ip address struct
struct sockaddr_in saddrin1;
saddrin1.sin_family = AF_INET;
saddrin1.sin_port = htons(12345);
saddrin1.sin_addr.s_addr = INADDR_ANY;
// bind socket to host
int ret = bind(soct1,(sockaddr*)&saddrin1,sizeof(saddrin1));
if(ret == -1)
{
std::cout<<"bind failled!"<<std::endl;
return -1;
}
// set listen
ret =listen(soct1,10);
if(ret == -1)
{
std::cout<<"listen failled!"<<std::endl;
return -1;
}
// init ip address
struct sockaddr_in saddrin2;
socklen_t addrlen =sizeof(saddrin2);
// access connect
int acc1 = accept(soct1,(sockaddr*)&saddrin2,&addrlen);
if(ret == -1)
{
std::cout<<"connect failled!"<<std::endl;
return -1;
}

// show c_ip addr
char ip[32];
cout<<inet_ntop(AF_INET,&saddrin2.sin_addr.s_addr,ip,sizeof(ip))<<"\n\n";
// make read buffer
char buff[1024];
// read
while(true)
{
int len = recv(acc1,buff,sizeof(buff),0);
if(len>0)
{
cerr<<buff<<endl;
memset(buff,0,sizeof(buff));
sprintf(buff,"hello customer!");
send(acc1,buff,strlen(buff)+1,0);
}
else if(len = 0)
{
break;
}
else
{
cerr<<"ERR";
break;
}
}
// clean connect
close(soct1);
close(acc1);

return 0;
}

通信流程

1. 服务器端

1
2
3
4
5
6
int soc=socket(); //创建用于监听连接的套接字(文件描述符)检测是否有客户端连接
bind() //将得到的文件描述符和本地IP端口绑定
listen(); //启动监听
int acp=accept(); //接受请求,返回 用于接受连接后用于通信的文件描述符
read();write();recv();send() //读写数据
close() //断开连接

2. 服务器端

```C++
int soc=socket(); //创建用于通信的文件描述读
connect(); //连接服务器
read(); //读写
write(); //读写
recv(); //读写
send();//读写
close(); //断开连接

C++多线程

一、 概念

1. 进程

可简单理解为exe的一次运行

2. 线程

一个进程可以有多个线程(但有且只有一个主线程)

二、 并发实现

1. 多进程

解决进程间通讯

2. 多线程

一个主线程多个子线程实现并发,进程资源在线程间共享

三、 C++线程创建

3.1 基本函数创建

1. 包含头文件

1
#include <thread>

2. 创建线程

创建thread对象

1
thread th1(func);
  • 需要后续处理:否则主函数结束会抛异常

    3. 后续处理

  1. 阻塞主线程
    1
    th1.join();
    主线程等待子线程执行完毕
  2. 分离子线程
    1
    th1.detach();
    将子线程与主线程分离,子线程与主线程不再关联
  • 每个线程只能做一次后续处理,不管是join还是detach.
  1. 判断一个进程是否可以做后续处理
    1
    th1.joinable();

    3.2 类和对象创建

    重载括号运算符制作函数类,将函数类的对象作为线程参数

    3.3 Lambda表达式创建

    将lambda表达式作为参数

    3.4 带参创建

    传引用参数需要ref()包装

    3.5 带智能指针

    move()但是之后原智能指针销毁

    3.6 类成员函数创建

    1
    thread th1(成员函数指针,成员函数所属的对象,参数(可能需要包装))

    四、异步

    4.1 包含头文件

    1
    #include <future>

    4.2 创建未来返回值对象

    1
    future<type> fu1;

    4.3 异步运行

    1
    fu1=async(func/lambda)
  • 此时程序分出一个线程执行异步程序,并继续向后执行

    4.4 取回异步运行结果

1
fu1.get()
  • 此时异步程序若仍未执行完,将阻塞程序至异步程序执行完并取回值

    4.5 等待异步程序执行完毕但不需要返回结果

    1
    fu1.wait()

    4.6 仅等待一段时间(超时检测)

    1
    fu1.wait_for(chrono时间单位())
  • 如超时未执行完毕则返回future_status::timeout,按时执行完毕则返回future_status::ready

    4.7 不异步仅延迟至get时运行

    async第一个参数设为std::launch::deferred

    4.8 手动管理线程

    不使用async而是使用promise
    1
    std::promise<type> pr1=promise(func/lambda)
    在传入的可执行体中设置未来值pr1.set_value(),然后在外面get_future获取未来返回值对象,并进一步get获取未来值

    五、锁

    1. 导入头文件
    1
    #include <mutex>
    2. 创建锁对象
    1
    2
    mutex mtx1
    timed_mutex tmtx1 //可以等待一会的锁
    3. 基本操作
    1
    2
    mtx1.lock()  //加锁
    mtx1.lock() //解锁
  • 一个锁锁住就不能再锁,后面试图加锁的就会被阻塞至前一线程解锁
    4. 自动解锁
    1
    lock_guard gl1(mtx1)
  • 创建即加锁,离开作用域自动解锁
1
2
3
4
5
6
7
8
9
unique_lock<std::mutex> ul1(mtx1) //创建即加锁
unique_lock<std::mutex> ul1(mtx1,defer_lock) //创建时不加锁
unique_lock<std::mutex> ul1(mtx1,try_to_lock) //创建时尝试加锁但不阻塞
ul1.try_lock() //尝试加锁
ul1.try_lock_for() //尝试再一段时间内加锁(timed_mutex)
ul1.try_lock_until() //尝试在某个时间点之前加锁(timed_mutex)
ul1.owns_lock() //锁是不是自己的(try_to_lock结果)
ul1.lock() //手动加锁
ul1.unlock() //手动解锁
  • 锁所有权转移要用move()

    5. 读写分离锁
    1
    2
    3
    4
    5
    6
    shared_mutex sml1 //创建锁
    sml1.lock() //锁写
    sml1.unlock() //解锁写
    sml1.lock_shared() //读锁
    sml1.unlock_shared() //解锁读
    shared_lock sl1(shared_mutexd对象) //自动解锁(类似unique_lock)
  • 读锁可以锁多次,多个线程一起读,但读的时候不能写(计数)

  • 多个对象建议每个对象一个锁

6. 死锁
  1. 一个线程不要同时持有多个锁
  2. 线程的上锁顺序一致
  3. 使用lock(mtx1,mtx2,...)对多个锁上锁可以自动处理上锁顺序确保不产生死锁
  4. 使用scoped_lock sl1(mtx1,mtx2,...)对多个锁上锁可以确保不产生死锁并自动解锁
  5. 单个线程死锁可以用recursice_mutex代替mutex,每次加锁会加一个计数,计数0解锁,但是会有性能损失

六、条件变量

1. 导入头文件

1
#include <condition_variable>

2. 创建条件变量对象

1
condition_variable cv1

2. 等待条件

1
2
cv1.wait(锁,可以提供执行体如返回true才唤醒) //多个wait被唤醒时锁确保只有一个线程被运行,等待状态中锁会被暂时解锁

4. 发送唤醒信号(另一线程)

1
2
cv1.notify_one() //唤醒一个wait的线程
cv1.notify_all() //唤醒所有wait的线程
  • condition_variable只支持unique_lock,其他锁可以用condition_variable_any
  • 也有wait_for()wait_until(),会返回布尔值作为等待结果

    七、原子操作

    1
    atomic<type> name
    放弃分解和乱序优化,确保对该变量的操作是一次性的(不会有其他线程在插入分解后的执行序列)
    1
    2
    3
    4
    5
    +=
    -=
    *=
    &=
    |=

漏洞扫描

1. 概念
漏洞扫描器是一种能够自动在计算机、信息系统、网络及应用软件中寻找和发现安全弱点的程序。它通过网络对目标系统进行探测,向目标系统发生数据,并将反馈数据与自带的漏洞特征库进行匹配,进而列举目标系统上存在的安全漏洞.

BBQSQL BED cisco-auditing-tool
cisco-global-exploiter cisco-ocs cisco-torch
copy-router-config Doona DotDotPwn
HexorBase jSQL Injection Lynis
Nmap ohrwurm openvas
Oscanner Powerfuzzer sfuzz
SidGuesser SIPArmyKnife sqlmap
Sqlninja sqlsus THC-IPV6
tnscmd10g unix-privesc-check Yersinia
  1. Nessus
  2. OpenVAS

Nessus
scan

scan

模式 扫描内容
CISCO 扫描CISCO系统
DNS 扫描DNS服务器
Default Unix Accounts 扫描本地默认用户账户和密码
FTP 扫描FTP服务器
Firewalls 扫描代理防火墙
Gain a shell remotely 扫描远程获取的Shell
Geeral 扫描常用的服务
Netware 扫描网络操作系统
Peer-To-Peer File Sharing 扫描共享文件检测
Policy Compliance 扫描PCI DSS和SCAP信息
SCADA 扫描设置管理工具
SMTP Problems 扫描SMTP问题
SNMP 扫描SNMP相关信息
Service Detection 扫描服务侦察
Settings 扫描基本设置

OpenVAS

1
2
3
4
5
6
7
openvas-nvt-sync
openvassd
openvasmd --rebuild
openvasmd --backup
openvasmd -p 9390 -a 127.0.0.1
openvasad -a 127.0.0.1 -p 9393
gsad --http-only --listen=127.0.0.1 -p 9392
模式 扫描内容
Compliance 扫描Compliance漏洞
Default Accounts 扫描默认账号漏洞
Denial of Service 扫描拒绝服务漏洞
FTP 扫描FTP服务器漏洞
Ubuntu Local Security Checks 扫描Ubuntu系统的本地安全漏洞

finish