Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

太阳位置及辐射强度等属性的计算方法

发表于 2019-11-26

太阳位置是从地球表面观察时,太阳在天空中的位置,它是时间和地理位置两者的函数。计算给定地点和时间的太阳位置要经过下列三个步骤:

  • 计算太阳在黄道坐标系的位置
  • 转换到赤道坐标系统
  • 依据观测者的位置和时间,转换到地平坐标系

计算太阳黄道坐标的方法

黄道坐标系是以黄道作基准平面的天球坐标系统,多用作研究太阳系天体运动情况之用。如图1所示。

黄道坐标系

图1 黄道坐标系

黄道是由地球上观察太阳一年中在天球上的视运动所通过的路径,若以地球“不动”作参照的话就是太阳绕地球公转的轨道平面(黄道面)在天球上的投影。

黄道与天赤道相交于两点:春分点与秋分点(这两点称二分点);而黄道对应的两个几何极是北黄极(在天龙座)、与南黄极 (在剑鱼座)。

在黄道上与黄道平行的小圆称黄纬,符号β,以由黄道面向北黄极方向为正值(0°至90°),向南黄极方向则为负值。垂直黄道的经度称黄经,符号为λ,由春分点起由西向东量度(0°至360°)。像赤道坐标系中的赤经一样,以春分点做为黄经的起点。

此坐标系特别适合标示太阳系内天体的位置,大多数行星(水星和冥王星除外)与许多小行星轨道平面与黄道的倾角都很小,故其黄纬值(β)都不大。

太阳黄道坐标的近似计算方法如下:

先计算与格林尼治 2000.0年1月1日中午12:00(历元)相距的日数。如果你知道儒略日,则你的叙述会如下:

$$ n = \mathrm{JD} - 2451545.0 $$

以光行差修正太阳的平黄经,如下:

$$ L = 280.460^\circ + 0.9856474^\circ n $$

太阳的平近点角(实际上,是地球在轨道上绕着太阳,但是假设太阳绕着地球比较方便)如下:

$$ g = 357.528^\circ + 0.9856003^\circ n $$

根据需要将L和g多次加或减360°,让数值的范围调整到0°至 360°之间。

最后,太阳的黄经是:

$$ \lambda = L + 1.915^\circ \sin g + 0.020^\circ \sin 2g$$

太阳的黄纬是:

$$ \beta = 0 $$

太阳的黄纬不超过0.00033,

并且从太阳到地球的距离,以天文单位度量是:

$$ R = 1.00014 - 0.01671 \cos g - 0.00014 \cos 2g $$

计算太阳赤道坐标的方法

赤道坐标系统是使用得最广泛的天球坐标系统,他的元素是:

  • 赤纬($\delta$)
  • 赤经($\alpha$ )-也记为RA

他与地理坐标系统非常相似,因为两者使用相同的基准平面和相同的极点。地球的赤道在天球上的投影就称为天球赤道,相同的,地理极点在天球上的投影就是天极,如图2所示。

赤道坐标系

图2 赤道坐标系

在经过一夜或数个夜晚,就能看出来星星在天空中的位置移动了,当然,这并非恒星在天球上的运动,只是地球运动造成的。因为岁差和章动的影响,在相当长的时间间隔下所做的观测,就必须注明所使用的特殊历元,为行星、恒星、星系等等的位置做记录。现在使用的历元是J2000.0分点,稍早期使用的是B1950.0分点。

赤道坐标系统中与纬度相似的值是赤纬(缩写为Dec.),是天体在天球赤道上方或下方的角度。与经度对应的是赤经(缩写为RA),是与春分点的角度距离,不同于经度的是赤经以时、分、秒为单位,而非度、分、秒。

$\lambda$、$\beta$ 和 $R$ 构成太阳在黄道座标完整的位置。通过黄赤交角 $ε$ 的计算可以转换成赤道座标,计算方法如下:

赤经:

$$ \alpha = \arctan(\cos \epsilon \tan \lambda)$$

赤纬:

$$ \delta = \arcsin(\sin \epsilon \sin \lambda)$$

其中,黄赤交角不是固定不变的,它目前的值接近:

$$ \epsilon = 23.439^\circ - 0.0000004^\circ n $$

计算太阳地平坐标的方法

地平坐标系,又作地平座标系,是天球坐标系统中的一种,以观测者所在地为中心点,所在地的地平线作为基础平面,将天球适当的分成能看见的上半球和看不见(被地球本身遮蔽)的下半球。上半球的顶点(最高点)称为天顶,下半球的顶点(最低点)称为地底。如图3所示。

地平坐标系

图3 地平坐标系

地平坐标系统是:

  • 高度角(Altitude, Alt)或仰角又称地平纬度,是天体和观测者所在地的地平线的夹角,有时就称为高度或海拔标高(elevation, geometric height)。
  • 方位角(Azimuth, Az)又称地平经度,是沿着地平线测量的角度(由正北方为起点向东方测量)。

因此地平坐标系有时也被称为高度/方位(Alt/Az)坐标系统。

只要知道观测者的地理坐标与时间,就可以将地平坐标转换成赤道坐标,或是反过来将赤道坐标转换成地平坐标。(纬度在北极点是+90°,在赤道是0°,南极点是-90°。)

在数学公式中,以$A$代表方位,$a$代表高度。

以$\delta$ 表示赤纬,$H$ 表示时角。 $φ$ 为观测者所在地的纬度。

赤道坐标转为地平坐标的计算方法如下:

$$\sin a=\sin \phi \cdot \sin \delta +\cos \phi \cdot \cos \delta \cdot \cos H$$

$${\displaystyle \cos A\cdot \cos a=-\cos \phi \cdot \sin \delta +\sin \phi \cdot \cos \delta \cdot \cos H}$$

$${\displaystyle \sin A\cdot \cos a=\cos \delta \cdot \sin H}$$

有些人或许会试图将最后两个公式相除来加以简化,以消除$\cos a$,而只剩下$\tan A$。但是正切函数不能清楚的区别出象限,例如45°和225°是完全不同的方位,分别指向相对的东北方和西南方。

时角(HA)是天文学的名词,一个天体的时角被定义为该天体的赤经与当地的恒星时的差值。 在天文学和天文航海中,时角是在赤道坐标系中用于给出天球上点的方向的坐标之一。 一个点的时角是两个平面之间的角度:一个平面包含地轴和天顶(子午面),另一个平面是穿过该点与极点(地轴)的球面大圆切圆所形成的平面(赤经圈)。如图4所示。

时角

图3 时角

时角由天赤道平面上的橙色箭头指示。 箭头自天球天赤道的子午面至观测目标所在面的球面大圆处结束,该球面大圆也是赤经圈
时角由子午线确定,遵循的规则是在子午线的东边则为负时角,在子午线的西边则为正时角,或者向西为正的360度,时角与经度的换算方法为24h = 360°。

一个天体的时角表示该天体是否通过了当地的子午圈(中天)。其数值则表示了该天体与当地子午圈的角距离,并借用时间的单位,以小时来计量(1HA = 15度)。例如,一个天体的时角是2.5HA,就表示他已经在2.5个小时之前通过当地的子午圈,并且在当地子午圈的西方37.5度的距离上。负数则表示在多少小时之后将通过当地的子午圈。当然,当时角为0时的意思就是这个天体就在当地的子午圈上。

参考链接

  1. 太阳位置,by wikipedia.
  2. 儒略日,by wikipedia.
  3. 黄道坐标系,by wikipedia.
  4. 赤道坐标系统,by wikipedia.
  5. 地平坐标系,by wikipedia.
  6. 时角,by wikipedia.

经纬高与北天东坐标之间的转换方法

发表于 2019-11-16 | 更新于 2022-09-11

经纬高是地理坐标系的表示方法,北天东则是一种直角坐标系。它们之间通过直角坐标系原点的经纬度联系起来,并可相互转换。下面介绍它们之间的转换方法。

坐标系分类

目前常用的坐标系统分成两种:地理坐标系和直角坐标系。下面分别介绍这两种坐标系。

地理坐标系

地理坐标系一般是指由经度、纬度和相对高度组成的坐标系,能够标示地球上的任何一个位置。经度和纬度常合称为经纬度,把球面上的经纬度显示在平面地图上需要采用某种地图投影。

地理坐标系的用途很广泛,例如天文学上常用的黄道坐标系、赤道坐标系同样也是一种地理坐标系。

直角坐标系

笛卡尔坐标系(英语:Cartesian coordinate system,也称直角坐标系)在数学中是一种正交坐标系,由法国数学家勒内·笛卡尔引入而有此名。

二维的直角坐标系通常由两个互相垂直的坐标轴设定,通常分别称为x-轴和 y-轴;两个坐标轴的相交点,称为原点,通常标记为O,既有“零”的意思,又是英语“Origin”的首字母。每一个轴都指向一个特定的方向。这两个不同线的坐标轴,决定了一个平面,称为xy-平面,又称为笛卡尔平面。通常两个坐标轴只要互相垂直,其指向何方对于分析问题是没有影响的,但习惯性地,x-轴被水平摆放,称为横轴,通常指向右方;y-轴被竖直摆放而称为纵轴,通常指向上方。两个坐标轴这样的位置关系,称为二维的右手坐标系,或右手系。

直角坐标系也可以推广至三维空间与高维空间 (higher dimension)。在原本的二维直角坐标系,再添加一个垂直于x-轴,y-轴的坐标轴,称为z-轴。假若,这三个坐标轴满足右手定则,则可得到三维的直角坐标系。这z-轴与x-轴,y-轴相互正交于原点。在三维空间的任何一点P,可以用直角坐标${\displaystyle (x,\ y,\ z)}$来表达其位置。

直角坐标系的用途非常广泛。例如天文学上常用的赤道直角坐标系、地平坐标系是一种直角坐标系。地心地固坐标系、北天东坐标系、北东地坐标系都是一种直角坐标系。

转换方法

经纬高与北天东的转换方法,通常通过地心地固坐标系作为中介进行转换。例如,经纬高转北天东,首先将经纬高转地心地固坐标系,再将地心地固坐标系转北天东坐标系。北天东转经纬高亦如此。

经纬高转地心地固坐标系

地心地固坐标系的示意图如图1所示。

地心地固坐标系

图1 地心地固坐标系

地心地固坐标系转北天东

参考链接

  1. 地心地固坐标系,by wikipedia.
  2. 地球椭球,by wikipedia.
  3. 椭球体的重要参数和公式,by 一灯.
  4. how do I translate of lon/lat coordinate by some N-E meters distance on earth surface?,by stackoverflow.
  5. 笛卡尔坐标系,by wikipedia.
  6. 地理坐标系,by wikipedia.
  7. ECEF坐标系,by 深_蓝.
  8. 空间参考系统,by wikipedia.

CMake使用入门教程

发表于 2019-11-16 | 更新于 2022-10-26

近几年美国对中国的科技封杀十分严重,说不定哪天Windows操作系统就不让我们用了。因此,在构建C/C++项目时应考虑跨平台,哪天不让用Windows了,可以请容易的将项目移植到Linux上。不同系统平台有不同的C/C++编译器,不同编译器有不同的构建规则,针对每个平台的不同编译器编写构建规则十分复杂,幸好有CMake可简化构建规则的编写,实现一次编写,不同平台适用。下面简单介绍CMake的使用。

CMake简介

代码变成可执行文件,叫做编译(compile);先编译这个,还是先编译那个(即编译的安排),叫做构建(build)。

Make是最常用的构建工具,诞生于1977年,主要用于C语言的项目。但是实际上 ,任何只要某个文件有变化,就要重新构建的项目,都可以用Make构建。

Make工具有很多,例如 GNU Make ,QT 的 qmake ,微软的 MS nmake,BSD Make(pmake),Makepp,等等。这些 Make 工具遵循着不同的规范和标准,所执行的 Makefile 格式也千差万别。这样就带来了一个严峻的问题:如果软件想跨平台,必须要保证能够在不同平台编译。而如果使用上面的 Make 工具,就得为每一种标准写一次 Makefile ,这将是一件让人抓狂的工作。

CMake就是针对上面问题所设计的工具:它首先允许开发者编写一种平台无关的 CMakeList.txt 文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化 Makefile 和工程文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程。从而做到“Write once, run everywhere”。显然,CMake 是一个比上述几种 make 更高级的编译配置工具。一些使用 CMake 作为项目架构系统的知名开源项目有 VTK、ITK、KDE、OpenCV、OSG 等。

CMake教程入门

给工程起个名字

语法:

1
project(<PROJECT-NAME> [LANGUAGES] [<language-name>...])

该指令定义工程名称。例如:

1
project(UtilTool)

添加头文件目录INCLUDE_DIRECTORIES

语法:

1
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

它相当于g++选项中的-I参数的作用,也相当于环境变量中增加路径到CPLUS_INCLUDE_PATH变量的作用。例如:

1
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)

当头文件分散在不同层次和深度的目录中时,逐个使用include_directories命令添加包含目录十分麻烦,可使用如下方法递归加载各个目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
MARO(HEADER_DIRECTORIES return_list)
FILE(GLOB_RECURSE new_list src/*.h)
SET(dir_list "")
FOREACH(file_path ${new_list})
GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
SET(dir_list ${dir_list} ${dir_path})
ENDFOREACH()
LIST(REMOVE_DUPLICATES dir_list)
SET(${return_list} ${dir_list})
ENDMACRO()

HEADER_DIRECTORIES(header_dir_list)
include_directories(${CMAKE_CURRENT_LIST_DIR}/include ${header_dir_list})

添加需要链接的库文件目录LINK_DIRECTORIES

语法:

1
link_directories(directory1 directory2 ...)

它相当于g++命令的-L选项的作用,也相当于环境变量中增加LD_LIBRARY_PATH的路径的作用。

1
link_directories(${CMAKE_CURRENT_LIST_DIR}/lib)

向当前工程添加存放源文件的子目录ADD_SUBDIRECTORY

ADD_SUBDIRECTORY用于向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置。语法如下:

1
2
ADD_SUBDIRECTORY(source_dir [binary_dir]
[EXCLUDE_FROM_ALL])

上面的例子定义了将 src 子目录加入工程,并指定了编译输出路径为 bin 目录。如果不指定 bin 目录,那么编译的结果都将存放在 build/src 目录。

设置要链接的库文件的名称TARGET_LINK_LIBRARIES

语法:

1
2
target_link_libraries(<target> [item1 [item2 [...]]]
[[debug|optimized|general] <item>] ...)

该指令的作用为将目标文件与库文件进行链接。例如:

1
TARGET_LINK_LIBRARIES(utiltool-example utiltool)

为工程生成目标文件

语法:

1
2
3
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...])

例如:

1
ADD_EXECUTABLE(utiltool-example examples/ConverterTest.cpp)

为工程生成共享库

语法:

1
2
3
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[source1] [source2] [...])

该指令的主要作用就是将指定的源文件生成链接文件,然后添加到工程中去。例如:

1
ADD_LIBRARY(utiltool SHARED ${UTILTOOL_SOURCES})

为工程制作简单的安装脚本

语法:

1
2
3
4
5
6
7
8
9
install(TARGETS targets... [EXPORT <export-name>]
[[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE|
PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[OPTIONAL] [NAMELINK_ONLY|NAMELINK_SKIP]
] [...])

该命令为一个工程生成安装规则。TARGETS格式的install命令规定了安装工程中的目标(targets)的规则。有5中可以被安装的目标文件:ARCHIVE,LIBRARY,RUNTIME,FRAMEWORK,和BUNDLE。静态链接的库文件总是被当做ARCHIVE目标。模块库总是被当做LIBRARY目标。例如:

1
2
3
4
5
install(TARGETS utiltool 
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib)
install(FILES ${UTILTOOL_HEADERS} DESTINATION include)

为工程设置变量

语法:

1
2
set(<variable> <value>
[[CACHE <type> <docstring> [FORCE]] | PARENT_SCOPE])

该指令用于给一般变量,缓存变量,环境变量赋值。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
# set up versioning.
set(BUILD_MAJOR "1")
set(BUILD_MINOR "0")
set(BUILD_VERSION "0")
set(BUILD_VERSION ${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_VERSION})

SET(UTILTOOL_HEADERS
src/GeodeticConverter.h
)

SET(UTILTOOL_SOURCES
src/GeodeticConverter.cpp
)

为工程设置预定义宏

语法:

1
add_definitions(-DFOO -DBAR ...)

该指令添加编译参数。例如:

1
2
# 添加WIN32宏定义
add_definitions(-DWIN32)

OPTION变量

语法:

1
2
option(<option_variable> "help string describing option"
[initial value])

该指令提供一个用户可以任选的选项,可在之后由用户通过CMake的GUI或者命令行进行更改。例如:

1
OPTION(UTILTOOL_EXAMPLES "Build the examples" ON)

修改默认的CMAKE_MODULE_PATH目录

CMAKE_MODULE_PATH是供find_package搜索第三方库用的。cmake的默认Modules目录在安装目录中:cmake-3.11.3-win64-x64\share\cmake-3.11\Modules。
如果要追加Modules目录,有3种方式:

1
2
3
4
5
SET(CMAKE_MODULE_PATH "${OpenSceneGraph_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}")

LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_PREFIX}")

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

find_package用法

通常情况下,包含第三方库需要写以下内容:

1
2
3
4
include_directories("${project_root_path}/include/")  
link_directories(./lib)
add_executable(myapp myapp.cpp)
target_link_libraries(myapp mylib)

如果引用的很多个第三方库,那么类似上面的内容会写很多,且如果自己的多个项目都引用了某个第三方库,那么我每个项目的CmakeList.txt都得写一遍,重复劳动很多。那么有没办法为每个第三方库只定义一次它的头文件和库文件信息,然后在自己的工程中只指定名称即可?(类似编译Java的Maven仓库)答案是当然可以,find_package帮你解决。

find_package定义在自己工程的CmakeList.txt中:

1
find_package( XXX CONFIG REQUIRED )

然后cmake就会在默认的Modules(即CMAKE_MODULE_PATH指定的目录)目录中搜索这个XXX第三方库。

搜索有两种模式:FindXXX.cmake和XXXConfig.cmake。前者叫做Module模式,后者叫做Config模式。

优雅的软件项目结构模板

请参考CMake—优雅地构建软件项目实践(1)。

完整简单示例

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
82
83
# CMakeList.txt: UtilTool 的 CMake 项目,在此处包括源代码并定义
# 项目特定的逻辑。
#
cmake_minimum_required (VERSION 3.8)

project(UtilTool)

# set up versioning.
set(BUILD_MAJOR "1")
set(BUILD_MINOR "0")
set(BUILD_VERSION "0")
set(BUILD_VERSION ${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_VERSION})

include_directories(${CMAKE_CURRENT_LIST_DIR}/include)

link_directories(${CMAKE_CURRENT_LIST_DIR}/lib)

link_libraries(gsl)

# OS and compiler checks.
if(UNIX)
# linux / normal unix
add_definitions(-D_LINUX)
if(CYGWIN)
# Special Cygwin stuff here
elseif(APPLE)
# Special Apple stuff here
remove_definitions(-D_LINUX)
add_definitions(-D_DARWIN)
endif()
elseif(WIN32)
add_definitions(-DWIN32)
add_definitions(-D UtilTool_EXPORTS)
if(MINGW)
# Special MINGW stuff here
elseif(MSVC)
# Special MSVC stuff here
add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS)
else()
# No idea what it is, but there's a good chance it's too weird.
MESSAGE( FATAL_ERROR "Using unknown WIN32 compiler... NOT. Please add to build system." )
endif()
endif()

SET(UTILTOOL_HEADERS
src/GeodeticConverter.h
)

SET(UTILTOOL_SOURCES
src/GeodeticConverter.cpp
)

# mark headers as headers...
SET_SOURCE_FILES_PROPERTIES( ${UTILTOOL_HEADERS} PROPERTIES HEADER_FILE_ONLY TRUE )
# append to sources so that dependency checks work on headers
LIST(APPEND UTILTOOL_SOURCES ${UTILTOOL_HEADERS})

OPTION(UTILTOOL_SHARED "Build utiltool lib as shared." ON)
OPTION(UTILTOOL_DEP_ONLY "Build for use inside other CMake projects as dependency." OFF)

# 将源代码添加到此项目的共享库中。
if(UTILTOOL_SHARED)
ADD_LIBRARY(utiltool SHARED ${UTILTOOL_SOURCES})
endif()

# install into configured prefix
if(NOT UTILTOOL_DEP_ONLY)
install(TARGETS utiltool
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib)
install(FILES ${UTILTOOL_HEADERS} DESTINATION include)
else()

endif()

# TODO: 如有需要,请添加测试并安装目标。
OPTION(UTILTOOL_EXAMPLES "Build the examples" ON)

if(UTILTOOL_EXAMPLES)
ADD_EXECUTABLE(utiltool-example examples/ConverterTest.cpp)
TARGET_LINK_LIBRARIES(utiltool-example utiltool)
endif()

参考链接

  1. Linux平台编译安装测试JSBSim,by jackhuang.
  2. 干货:构建C/C++良好的工程结构,by Froser.
  3. 基于CMake构建系统的C++工程框架,by zhongxiao_yao.
  4. CMake 手册详解(十九)install指令,by SirDigit.
  5. CMake中变量总结,by 拾荒志.
  6. cmake使用教程(十)-关于file,by saka.
  7. Recursive CMake search for header and source files,by stackoverflow.
  8. CMake shared library in subdirectory,by stackoverflow.
  9. CMake 语言和语法,by leosocy.
  10. 【cmake】——include_directories 和target_include_directories的区别,by 大川搬砖.
  11. CMake—优雅地构建软件项目实践(1),by Ethan.
  12. CMake测试,by dxa572862121.
  13. CMake–Set用法,by narjaja.
  14. CMake之message()函数的使用和打印变量值,by hp_cpp.
  15. A minimal CMake project template,by Matt Morse.
  16. [Build]cmake常用配置项,by 玄冬Wong.
  17. 简单介绍Cmake生成VS工程中的ALL_BUILD、INSTALL、ZERO_CHECK作用!!,by 醉逍遥_祥.

C++常用库简介

发表于 2019-11-15 | 更新于 2022-12-07

为熟练使用C++创建项目,应掌握常用的C++库。现总结常用的C++库如下:

数学库

gsl(GNU Scientific Library):GUN科学运算库

Blitz++:高效率的数值计算函数库

它的设计目的是希望建立一套既具像C++ 一样方便,同时又比Fortran速度更快的数值计算环境。通常,用C++所写出的数值程序, 比 Fortran慢20%左右,因此Blitz++正是要改掉这个缺点。方法是利用C++的template 技术,程序执行甚至可以比Fortran更快。

MTL(Matrix Template Library):矩阵模板库

专注于线性代数相关的计算任务,如各种形式矩阵的生成(对角,共轭,稀疏,对称等),相关的计算,变换,以及与一维向量的运算。

POOMA

一个免费的高性能的C++库,用于处理并行式科学计算。POOMA的面向对象设计方便了快速的程 序开发,对并行机器进行了优化以达到最高的效率,方便在工业和研究环境中使用。

CGAL:计算几何算法库

Computational Geometry Algorithms Library的目的是把在计 算几何方面的大部分重要的解决方案和方法以C++库的形式提供给工业和学术界的用户。
是一个大型C + +库的几何数据结构和算法,如Delaunay三角网,网格生成,布尔运算的多边形,以及各种几何处理算法。 CGAL是用来在各个领域:计算机图形学,科学可视化,计算机辅助设计与建模,地理信息系统,分子生物学,医学影像学,机器人学和运动规划,和数值方法。

Matlab的开源高仿 Octave

旨在解决线性和非线性的数值计算问题。也是跨平台的,源码中用了大量m4语言。

C++符号计算库 GiNaC

Eigen -目前较活跃

线性代数、矩阵、向量操作等运算的C++库。推荐使用。

C/C++数值计算库 mygsl

mygsl是一个基于GSL库的个性化开源数值计算项目.

IMSL

软件名称 IMSL C Numerical Library(不兼容vc6 编译器)。

分为统计库和数学库两部分。数学库包含应用数学和特殊函数。IMSL 程序库已成为数值分析解决方案的工业标准。 IMSL 程序库提供最完整与最值得信赖的函数库。 IMSL 数值程序库提供目前世界上最广泛被使用的 IMSL 算法,有超过 370 验证过、最正确与 thread-safe 的数学与统计程序。 IMSL FORTRAN 程序库提供新一代以 FORTRAN 90 为程序库基础的程序,能展现出最佳化的演算法能力应用于多处理器与其它高效能运算系统。

网络库

ACE

庞大、复杂,适合大型项目。开源、免费,不依赖第三方库,支持跨平台。

Asio

Asio基于Boost开发的异步IO库,封装了Socket,简化基于socket程序的开发。

开源、免费,支持跨平台。

POCO

POCO C++ Libraries 提供一套 C++ 的类库用以开发基于网络的可移植的应用程序,功能涉及线程、线程同步、文件系统访问、流操作、共享库和类加载、套接字以及网络协议包括:HTTP、 FTP、SMTP 等;其本身还包含一个 HTTP 服务器,提供 XML 的解析和 SQL 数据库的访问接口。POCO库的模块化、高效的设计及实现使得POCO特别适合嵌入式开发。在嵌入式开发领域,由于C++既适合底层(设备I/O、中断处理等)和高层面向对象开发,越来越流行。

libevent

Libevent是一个轻量级的开源高性能网络库,从它的官网标题:libevent-an event notification library就能知道它的机制是采用事件触发,封装了以下三种事件的响应:IO事件,定时器事件,信号事件。select模型来实现跨平台的操作,Windows环境下支持IOCP。Google的开源WEB浏览器Chromium在Mac和Linux版本中,也使用了Libevent,足见该库的质量。

libev

libev和libevent很像,按照作者的介绍,可以作为libevent的替代者,能够提供更高的性能。

libev是一个高性能事件循环,所实现的功能就是一个强大的reactor。

c++ sockets library

封装了sockets C API的C++类库。

支持SSL, IPv6, tcp 和 udp sockets, sctp sockets, http协议, 高度可定制的错误处理。

libcurl

libcurl是免费的轻量级的客户端网络库,支持DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet, TFTP. 支持SSL, HTTP POST, HTTP PUT, FTP上传, HTTP form上传,代理,cookies, 用户名与密码认证。

如果你开发的是客户端,libcurl是一个不错的选择。

clsocket

clsocket是一组轻量级的类,允许开发人员实现基于IP的网络程序。这个编译简单而且用起来也简单,推荐使用。

日志库

spdlog

参考链接

  1. C++数学库,by xigua1234.
  2. c++中关于M_PI,M_E的解释和使用,以及参考值,by SYITwin.
  3. GSL with CMake build support,by ampl.
  4. 在Visual Studio中使用GNU Scientific Library (GSL),by NULL_BOT.
  5. 开源免费的C/C++网络库(c/c++ sockets library) 七剑下天山,by 工程师WWW.
  6. 值得推荐的C/C++框架和库 (真的很强大),by tibet889.
  7. 有哪些值得推荐的c/c++开源框架与库,by 零声学院.
  8. C++ std::isnan等函数的使用,by ccf19881030.
  9. C/C++log日志库比较,by shy丶gril.

Web应用压力测试方法

发表于 2019-11-12 | 更新于 2019-11-25

Web应用在部署前,最好进行压力测试,以衡量其是否达到设计指标,判断其在何种极限条件下应用功能会失效。下面即介绍软件测试中压力测试,尤其是Web应用压力测试的相关知识。

压力测试

压力测试(英语:Stress testing)是针对特定系统或是组件,为要确认其稳定性而特意进行的严格测试。会让系统在超过正常使用条件下运作,然后再确认其结果。进行压力测试的原因可能包括:

  • 确认系统在什么条件下会损坏,以及安全使用条件。
  • 确认预测系统在什么条件下会损坏或其安全使用条件的数学模型是否准确。
  • 确认是否符合预期的规格。
  • 确认失效原因。
  • 确认系统在正常工作条件以外,是否可以正常运作。

软件测试中的压力测试是在超过正常运作条件以外的条件下运作系统,以确认健壮性的方式。压力测试对于关键任务软件格外的重要,但可以适用于各种的软件。压力测试一般较强调软件在高负载下的健壮性、可用性及异常处理,以及哪些在一般使用环境下算是正常行为。

例如一个网站设计容量是100个人同时点击,压力测试就要是采用120个同时点击的条件测试。

性能指标

web应用的性能指标主要有响应时间,吞吐量,并发量,性能计数器。

响应时间

响应时间指应用执行一个操作需要的时间,即从发出请求到最后收到响应数据所需要的时间。例如:打开一个网站的响应时间、数据库查询一条记录(有索引)的响应时间等等。

实践中通常采用的办法是重复请求,比如一个请求操作重复执行1万次,测试一万次执行的总响应时间之和,然后除以1万,就得到单次请求的响应时间。

吞吐量

吞吐量指单位时间内系统处理的请求数量,体现系统的整体处理能力。对于网站,可用“请求数/秒”、“页面数/秒”或“访问人数/天”、“处理业务数/小时”等来衡量。重要指标有TPS(每秒处理的事物数)、QPS(每秒查询的请求数)、HPS(每秒HTTP请求数)等。

并发量

并发量指系统能够同时处理的请求的数目,这个数字反映了系统的负载性能。对于网站而言,并发数指网站用户同时提交请求的用户数目。

性能计数器

性能计数器描述服务器或操作系统性能的一些数据指标。如System Load、对象与线程数、内存使用、CPU使用、磁盘与网络I/O等使用情况。通过对这些指标设置报警阈值,当监控系统发现性能计数器超过阈值时,就向开发人员和运维报警,及时发现异常并处理。

测试工具

压力测试工具有http_load、apache ab、siege。

参考链接

  1. 压力测试,by wikipedia.
  2. 压力测试 (软件),by wikipedia.
  3. 网站性能测试指标及网站压力测试,by 呦呦鹿鸣.
  4. Web 性能压测工具 ApacheBench(ab)使用总结,by juejin.

Axios请求超时处理方法

发表于 2019-11-11

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。Vue2官方推荐使用Axios执行HTTP请求和处理HTTP响应。Axios具有如下特征:

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

下面介绍使用Axios的拦截功能实现Axios超时错误的统一处理。

Axios基本用法

执行 GET 请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});

// 可选地,上面的请求可以这样做
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});

执行 POST 请求:

1
2
3
4
5
6
7
8
9
10
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});

执行多个并发请求:

1
2
3
4
5
6
7
8
9
10
11
12
function getUserAccount() {
return axios.get('/user/12345');
}

function getUserPermissions() {
return axios.get('/user/12345/permissions');
}

axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// 两个请求现在都执行完成
}));

Axios拦截器

自定义 axios 实例添加拦截器,在请求或响应被 then 或 catch 处理前拦截它们。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// create an axios instance
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout
})

// 添加请求拦截器
service.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});

// 添加响应拦截器
service.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});

拦截timeout错误

在Axios响应拦截器中,处理timeout错误,代码如下:

1
2
3
4
5
6
7
8
9
10
11
service.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
if(error.message.includes('timeout')){ // 判断请求异常信息中是否含有超时timeout字符串
console.log("错误回调", error);
alert("网络超时");
}
return Promise.reject(error);
});

参考链接

  1. Axios使用说明,by yunye.
  2. axios超时timeout拦截,by 亲爱的混蛋.

C++标准模板库STL入门

发表于 2019-11-10

最近C++编程中需要管理多个由同一个类实例化的对象,于是想到了C++的标准模板库STL,在此将STL的相关知识记录一下。

STL的来龙去脉

STL 历史可以追溯到 1972 年 C 语言在 UNIX 计算机上的首次使用。直到 1994 年,STL 才被正式纳入 C++ 标准中。

标准模板库(STL)是 C ++编程语言的软件库,影响了C ++标准库的许多部分。它提供了四个组件,分别称为算法,容器,仿函数和迭代器。

STL为 C ++提供了一组通用类,例如容器和关联数组,可以与任何内置类型和支持某些基本操作(例如复制和赋值)的任何用户定义类型一起使用。 STL算法独立于容器,从而大大降低了库的复杂性。

STL通过使用模板来实现其结果。这种方法提供的编译时多态性通常比传统的运行时多态性更有效。对现代 C ++编译器进行了调整,以最大程度地减少由于大量使用STL而引起的抽象损失。

STL是创建的第一个C ++通用算法和数据结构库,它牢记四个想法:通用编程,不损失效率的抽象性,冯·诺依曼计算模型和值语义。

STL 组件

STL 将“在数据上执行的操作”与“要执行操作的数据分开”,分别以如下概念指代:

  • 容器:包含、放置数据的地方。
  • 迭代器:在容器中指出一个位置、或成对使用以划定一个区域,用来限定操作所涉及到的数据范围。
  • 算法:要执行的操作。

容器

容器即用来存储并管理某类对象的集合。例如鱼缸是用来盛放金鱼的容器。标准模板库中容器主要分为序列容器(sequence containers)与关系容器(associative containers)。

序列容器包括:

  • vector
  • list
  • forward_list
  • deque
  • array

关联容器包括:

  • set
  • multiset
  • map
  • multimap
  • unordered_set
  • unordered_multiset
  • unordered_map
  • unordered_multimap

其他类型的容器包括:

  • bitset
  • valarray

迭代器

迭代器用于在一个对象群集的元素上进行遍历动作。对象群集可能是容器,也可能是容器的一部分。

迭代器的主要用途是为容器提供一组很小的公共接口。利用这个接口,某项操作可以行进至群集内的下一个元素。

每种容器都提供了各自的迭代器。迭代器了解该容器的内部结构,所以能够正确行进。迭代器的接口和一般指针类似。

迭代器的作用就是提供一个遍历容器内部所有元素的接口,因此迭代器的内部必须保存一个与容器相关联的指针,然后重载各种运算操作来方便遍历,其中最重要的就是∗运算符和->运算符,以及++,–等可能需要的运算符重载。

根据迭代器的操作方式的不同,迭代器分为五种:

  • 输入迭代器
  • 输出迭代器
  • 前向迭代器
  • 双向迭代器
  • 随机访问迭代器

迭代器的示例代码如下:

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
#include <iostream>
#include <vector>

using namespace std;

int main()
{
vector<int> v; // 定义一个vector容器

v.push_back(1); // 向容器中添加3个元素
v.push_back(2);
v.push_back(3);

// 遍历向量的元素
vector<int>::iterator b = v.begin(); // 指向容器的第一个元素
vector<int>::iterator e = v.end(); // 指向容器尾元素的下一个位置

// C++11新标准的写法, auto关键字为类型推断,由编译器自动完成
// auto b = v.begin();
// auto e = v.end();

for (vector<int>::iterator iter = b; iter != e; ++iter)
{
cout << *iter << endl;
}

return 0;
}

算法

算法用来处理群集内的元素,可以出于不同目的搜寻、排序、修改、使用那些元素。所有容器的迭代器都提供一致的接口,通过迭代器的协助,算法程序可以用于任意容器。

STL 的一个特性是将数据和操作分离。数据由容器类别加以管理,操作则由可定制的算法定义。迭代器在两者之间充当“粘合剂”,以使算法可以和容器交互运作。

STL 的另一个特性即组件可以针对任意型别运作。“标准模板库”这一名称即表示“可接受任意型别”的模板,并且这些型别均可执行必要操作。

仿函数

STL中大量运用了仿函数。仿函数具有泛型编程强大的威力,是纯粹抽象概念的例证。

参考链接

  1. STL教程:C++ STL快速入门,by C语言中文网.
  2. STL是什么(STL简介),by C语言中文网.
  3. 标准模板库,by wikipedia.
  4. C++ STL初识及整理,by thinkChao.
  5. C++标准模板库(STL)迭代器的原理与实现,by wutao02.

异常处理的一些理解

发表于 2019-11-02

在编程过程,经常遇到的一个问题是如何优雅地处理异常。下面给出一些对这个问题的答案。

异常处理定义

异常处理,是编程语言或计算机硬件里的一种机制,用于处理软件或信息系统中出现的异常状况(即超出程序正常执行流程的某些特殊条件)。

异常处理与错误检测的区别

错误检测与异常处理区别在于:错误检测是在正常的程序流中,处理不可预见问题的代码,例如一个调用操作未能成功结束。

某些编程语言有这样的函数:当输入存在非法数据时不能被安全地调用,或者返回值不能与异常进行有效的区别。例如,C语言中的atoi函数(ASCII串到整数的转换)在输入非法时可以返回0。在这种情况下编程者需要另外进行错误检测(可能通过某些辅助全局变量如C的errno),或进行输入检验(如通过正则表达式),或者共同使用这两种方法。

通过异常处理,我们可以对用户在程序中的非法输入进行控制和提示,以防程序崩溃。从进程的视角,硬件中断相当于可恢复异常,虽然中断一般与程序流本身无关。从子程序编程者的视角,异常是很有用的一种机制,用于通知外界该子程序不能正常执行。如输入的数据无效(例如除数是0),或所需资源不可用(例如文件丢失)。如果系统没有异常机制,则编程者需要用返回值来标示发生了哪些错误。

异常处理的原则

为了更好的处理异常,应遵循以下三个原则:

  • 具体明确
  • 提早抛出
  • 延迟捕获

具体明确

捕获异常时具体明确有利于对异常进行恰当的处理。例如在Java中对同一try块定义多个catch块,以便对每种异常分别进行恰当的处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
File prefsFile = new File(prefsFilename);

try{
readPreferences(prefsFile);
}
catch (FileNotFoundException e){
// alert the user that the specified file
// does not exist
}
catch (EOFException e){
// alert the user that the end of the file
// was reached
}
catch (ObjectStreamException e){
// alert the user that the file is corrupted
}
catch (IOException e){
// alert the user that some other I/O
// error occurred
}

提早抛出

异常堆栈信息提供了导致异常出现的方法调用链的精确顺序,包括每个方法调用的类名,方法名,代码文件名甚至行数,以此来精确定位异常出现的现场。例如:

1
2
3
4
5
6
7
java.lang.NullPointerException
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:103)
at jcheckbook.JCheckbook.readPreferences(JCheckbook.java:225)
at jcheckbook.JCheckbook.startup(JCheckbook.java:116)
at jcheckbook.JCheckbook.<init>(JCheckbook.java:27)
at jcheckbook.JCheckbook.main(JCheckbook.java:318)

通过逐步回退跟踪堆栈信息并检查代码,可以确定错误原因。

延迟捕获

捕获异常后怎么处理?最不该做的就是什么都不做。空的catch块等于把整个异常丢进黑洞,能够说明何时何处为何出错的所有信息都会永远丢失。把异常写到日志中还稍微好点,至少还有记录可查。但我们总不能指望用户去阅读或者理解日志文件和异常信息。

因此,不要过早捕获异常,而是在合适的层面捕获异常,以便你的程序要么可以从异常中有意义地恢复并继续下去,而不导致更深入的错误;要么能够为用户提供明确的信息,包括引导他们从错误中恢复过来。如果你的方法无法胜任,那么就不要处理异常,把它留到后面捕获和在恰当的层面处理。

参考链接

  1. 异常处理,by wikipedia.
  2. 如何优雅的处理异常(java)?,by zhihu.

Linux防SYN_Flood攻击的方法

发表于 2019-10-30 | 更新于 2023-01-20

最近管理的Linux服务器遭遇了SYN Flood攻击,因此研究一下防范该攻击的方法。

SYN Flood攻击的表现

使用ssh登录Linux服务器,在终端中输入netstat -antp能查看到有大量的链接时SYN_RECV状态,说明Linux服务器遭遇了SYN Flood攻击。

netstat常用参数

netstat常用参数如下:

  • -a (all)显示所有选项,默认不显示LISTEN相关
  • -t (tcp)仅显示tcp相关选项
  • -u (udp)仅显示udp相关选项
  • -n 拒绝显示别名,能显示数字的全部转化成数字。
  • -l 仅列出有在 Listen (监听) 的服務状态
  • -p 显示建立相关链接的程序名
  • -r 显示路由信息,路由表
  • -e 显示扩展信息,例如uid等
  • -s 按各个协议进行统计
  • -c 每隔一个固定时间,执行该netstat命令。

TCP连接状态

  • ESTABLISHED

指TCP连接已建立,双方可以进行方向数据传递

  • CLOSE_WAIT

这种状态的含义其实是表示在等待关闭。当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。

  • LISTENING

指TCP正在监听端口,可以接受链接

  • TIME_WAIT

指连接已准备关闭。表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。

  • FIN_WAIT_1

FIN_WAIT_1和 FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报 文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN 报文,此时该SOCKET即进入到FIN_WAIT_1 状态。而当对方回应ACK 报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况 下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2 状态还有时常常可以用 netstat看到。

  • FIN_WAIT_2

FIN_WAIT_2 状态下的SOCKET,表示半连接,也即有一方要求close 连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。

  • LAST_ACK

是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了

  • SYNC_RECEIVED

表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。

  • SYNC_SEND

已经主动发出连接建立请求。与SYN_RCVD遥想呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。

防范措施

首先确保ssh登录密码没有泄露,再修改系统相关配置。

剔出其他登录用户

当ssh登录密码泄露,会有其他用户登录,所以需要剔出其他登录用户,再修改密码和系统相关配置。剔出其他登录用户的方法如下:

  • 查看系统在线用户
1
2
3
4
5
[root@apache ~]# w 
14:15:41 up 42 days, 56 min, 2 users, load average: 0.07, 0.02, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 116.204.64.165 14:15 0.00s 0.06s 0.04s w
root pts/1 116.204.64.165 14:15 2.00s 0.02s 0.02s –bash
  • 查看当前自己占用终端,防止把自己干掉了
1
2
[root@apache ~]# who am i 
root pts/0 2013-01-16 14:15 (116.204.64.165)
  • 用pkill 命令剔除对方
1
2
# 信号代码 -9 ,表示强制终止
[root@apache ~]# pkill -9 -t pts/1
  • 用w命令在看看干掉没。
1
2
3
4
[root@apache ~]# w 
14:19:47 up 42 days, 1:00, 1 user, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 116.204.64.165 14:15 0.00s 0.03s 0.00s w

抵御SYN攻击的方法

SYN攻击是利用TCP/IP协议3次握手的原理,发送大量的建立连接的网络包,但不实际建立连接,最终导致被攻击服务器的网络队列被占满,无法被正常用户访问。

修改SYN相关系统配置

Linux内核提供了若干SYN相关的配置,用命令: sysctl -a | grep syn 看到:

1
2
3
4
net.ipv4.tcp_max_syn_backlog = 1024 
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_synack_retries = 5
net.ipv4.tcp_syn_retries = 5

tcp_max_syn_backlog是SYN队列的长度,tcp_syncookies是一个开关,是否打开SYN Cookie 功能,该功能可以防止部分SYN攻击tcp_synack_retries和tcp_syn_retries定义SYN 的重试次数。  

加大SYN队列长度可以容纳更多等待连接的网络连接数,打开SYN Cookie功能可以阻止部分 SYN攻击,降低重试次数也有一定效果。

调整上述设置的方法是:

1
2
3
4
5
6
7
8
9
# 增加SYN队列长度到2048:
sysctl -w net.ipv4.tcp_max_syn_backlog=2048

# 打开SYN COOKIE功能:
sysctl -w net.ipv4.tcp_syncookies=1

# 降低重试次数:
sysctl -w net.ipv4.tcp_synack_retries=3
sysctl -w net.ipv4.tcp_syn_retries=3

为了系统重启动时保持上述配置,可将上述命令加入到/etc/rc.d/rc.local文件中。

iptables阻止syn flood攻击

防止同步包洪水(Sync Flood):

1
2
# –limit 1/s 限制syn并发数每秒1次,可以根据自己的需要修改
iptables -A FORWARD -p tcp –syn -m limit –limit 1/s -j ACCEPT

防止各种端口扫描:

1
iptables -A FORWARD -p tcp –tcp-flags SYN,ACK,FIN,RST RST -m limit –limit 1/s -j ACCEPT

Ping洪水攻击(Ping of Death):

1
iptables -A FORWARD -p icmp –icmp-type echo-request -m limit –limit 1/s -j ACCEPT

屏蔽 SYN_RECV 的连接:

1
iptables -A INPUT -p tcp -m tcp –tcp-flags SYN,RST,ACK SYN -m limit –limit 1/sec -j ACCEPT

禁止某IP访问:

1
iptables -I INPUT -s xxx.xxx.xxx.xx -j DROP

参考链接

  1. LINUX 服务器遭到SYN FLOOD攻击,by 晓风残梦.
  2. Linux netstat命令详解,by ggjucheng.
  3. netstat 的10个基本用法,by LCTT bazz2.
  4. netstat用法及TCP state解析,by vigarbuaa.
  5. Linux踢出其他正在SSH登陆用户,by 艾欧里亚.
  6. [Linux] killall 、kill 、pkill 命令详解,by 骑着蜗牛游世界.
  7. Linux中kill,pkill,killall和xkill命令汇总讲解,by simonGeek.
  8. Linux防止syn flood攻击,屏蔽 SYN_RECV 的连接,by Sphinx 中文站.
  9. iptables,by wangchujiang.
  10. TCP状态机,by 大蟒传奇.

不同语言的计时方法

发表于 2019-10-27

剖析代码性能时通常需要计时。下面记录不同语言的各种计时方法。

C++计时方法

传统计时方法的代码如下:

1
2
3
4
5
6
7
#include <ctime>
using namespace std;

clock_t start = clock();
// do something...
clock_t end = clock();
cout << "花费了" << (double)(end - start) / CLOCKS_PER_SEC << "秒" << endl;

C++11 标准的”最佳计时方法“的代码:

1
2
3
4
5
6
7
8
9
10
11
#include <chrono>   
using namespace std;
using namespace chrono;

auto start = system_clock::now();
// do something...
auto end = system_clock::now();
auto duration = duration_cast<microseconds>(end - start);
cout << "花费了"
<< double(duration.count())
<< "微秒" << endl;

Python计时方法

在Jupyter Notebook中,计时使用一个magic command:%timeit。

参考链接

  1. C++11 新的计时方法——std::chrono 大法好,by sicolex.
上一页1…323334…53下一页

Jack Huang

523 日志
67 标签
© 2025 Jack Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse