项目地址:OrbitZore/HNUSTnet

因为湖科大的校园网存在莫名其妙的失去登录状态的问题,于是想写个项目解决。🤔

加上最近读《Effective C++》,想要考验一下自己的C++水平。于是就决定用C++实现。👏

粗略想了下技术栈。因为想体验一下跨平台,于是就上了cmake编译,附带使用boost::asio作为跨平台网络库。这样一个大体的框架就被敲定了,剩下就是艰难的实现过程了。

但在实现的过程中遇到了麻烦的编码问题。想要代码跨平台,字符常量最好使用UTF-8编码(代码内使用u8""声明一个字符串常量)。但是TCP上的HTTP传输内容编码为GB2312。考虑再三。舍弃掉代码内字符串分开编码的方案,使用Iconv这一C库将GB2312转换为UTF-8。

CMake

CMakeLists.txt

在命令行中运行cmake <DIR>cmake会检查目录下的CMakeLists.txt。并解释执行CMakeLists.txt内容。

声明项目名

project (<Project Name>)

包含子项目

add_subdirectory (<DIR>)

CMake会寻找目录下CMakeLists.txt,类似调用函数一样的调用解释执行此CMakeLists.txt

在项目中引入外部库

寻找外部库

库名一律首字母大写其他小写

find_package(<name>)

适用于一些C库Threads,Iconv

Boost依赖Threads

find_package(<name> COMPONENTS <lib1> [lib2 ...])

Boost这种包含很多子库的大库来说,为了避免引入不必要的库使编译缓慢。在寻找时指出子库成为了一个好选择。

本项目寻找Boost::system以解决Boost::Asio依赖问题

适用于一些大型C++库

find_path(BOOST_ASIO_INCLUDE_DIRS "boost/asio.hpp")

本项目会用到Boost.Asio,其为Headers Only类型的库。引入时只需Include头文件就行。这个语句作用为寻找Asio的头文件boost/asio.hpp,并将其目录赋值给BOOST_ASIO_INCLUDE_DIRS变量

find_package会在一些目录中寻找<name>.cmake的文件(其实还有找很多其他文件,因不在本项目内所以略过,可参考Cmake之深入理解find_package()的用法),其包含了寻找<name>这个库并引入到cmake的步骤。一般会初始化<name>_INCLUDE_DIRS<name>_LIBRARY_DIRS<name>_FOUND这三个常量。含义分别为这个库的头文件目录,*.obj目录,库是否找到了。

某些<name>.cmake会检查一些关于需要引用库的设置变量。本项目即用到了Boost_USE_STATIC_LIBS等,均可在下文介绍的文档中查询。

CMake中已经包含了一些热门库的<name>.cmake文件,本项目中所有库均为如此。官方文档地址cmake-modules(7) — CMake 3.19.1 Documentation

引入头文件

以下做法将会把头文件引入所有子项目。因本项目仅包含一个子项目所以此法可行。如多个子项目可使用target_系列函数。

include_directories(<DIRS1> [DIRS2 ...])
引入*.obj文件

以下做法将会把*.obj文件引入所有子项目。因本项目仅包含一个子项目所以此法可行。如多个子项目可使用target_系列函数。

link_libraries([item1 [item2 [...]]]
               [[debug|optimized|general] <item>] ...)

添加源代码和头文件至项目

add_executable (HNUSTnet <sources1> [sources2])

项目源代码文件说明

源代码文件名 说明
misc.cpp 提供一些工具函数
iconv.hpp 提供Iconv的C++封装 by Yuya Unno
TCPclient.cpp 基于Boost::Asio抽象TCP连接
HTTPclient.cpp 基于TCPclient.cpp提供简单的HTTP封装,并使用iconv.hpp转码
HNUSTnet.cpp 基于HTTPclient.cpp提供login.hnust.cn的API封装,并提供自动连接操作
main.cpp 命令行程序化HNUSTnet.cpp

依赖库相关资料

Boost::Asio官方文档

u1s1这官方文档比CPP reference难读多了..

Using Asio with C++11

介绍Asio的简单使用

Boost

Boost的各个子库