介紹
HP-Socket是一套通用的高性能TCP/UDP/HTTP 通信框架,包含服務端組件、客戶端組件和Agent組件,廣泛適用於各種不同應用場景的TCP/UDP/HTTP通信系統,提供C/C++、C#、Delphi、E(易語言)、Java、Python等編程語言接口。HP-Socket對通信層完全封裝,應用程序不必關注通信層的任何細節;HP-Socket提供基於事件通知模型的API接口,能非常簡單高效地整合到新舊應用程序中。
來自百度百科介紹。
對於這個庫,只是偶然間用到他的HTTP功能。雖然事情已經過去,但還是覺得這個庫有極大的學習和研究價值。可以學習鞏固網絡的一些基礎原理,框架,及語言的實現,並且有中文資料和類圖等,內容豐富。
編譯
下載Hp-socket庫:
git clone https://github.com/ldcsaa/HP-Socket.git
這個庫有多個系統的版本,我們這裏選用linux分析就好了。所以進入到Linux下,看readme大概知道編譯流程。
./compile.sh
sudo ./install.sh
大概就是分兩個腳本,一個編譯腳本和一個安裝腳本。-h參數可以分別看到他們的使用說明。
compile.sh腳本
$ ./compile.sh -h
Usage: compile.sh [...O.P.T.I.O.N.S...]
----------------------+-------------------------------------------------
-d|--with-debug-lib : compile debug libs (default: true)
-j|--use-jemalloc : use jemalloc in release libs
: (x86/x64 default: true, ARM default: false)
-u|--udp-enabled : enable UDP components (default: true)
-t|--http-enabled : enable HTTP components (default: true)
-s|--ssl-enabled : enable SSL components (default: true)
-z|--zlib-enabled : enable ZLIB related functions (default: true)
-i|--iconv-enabled : enable ICONV related functions (default: true)
-c|--compiler : compiler (default: g++)
-p|--platform : platform: x86 / x64 / ARM
: (default: current machine arch platform)
-e|--clean : clean compilation intermediate temp files
-r|--remove : remove all compilation target files
-v|--version : print hp-socket version
-h|--help : print this usage message
----------------------+-------------------------------------------------
大概就是選擇某個模塊進行編譯。
看看腳本邏輯
# 1.首先加載script/env.sh腳本里的變量和函數
source $PACKAGE_PATH/$SCRIPT_DIR/env.sh
# 2.解析參數:設置對應的編譯模塊的變量值並得到一個控制狀態ACTION_NAME
parse_args "$@"
# 3.顯示上一步解析得到的配置結果
print_config
# 4.不同action的操作
if [ $EXEC_FLAG -eq 1 ]; then
do_clean
elif [ $EXEC_FLAG -eq 2 ]; then
do_remove
else
do_build
fi
一般情況下我們用的是編譯,所以就是do_build函數
HPSOCKET_LIB_NAME=hpsocket
HPSOCKET4C_LIB_NAME=hpsocket4c
do_build()
{
# 設置一些編譯的變量
C_LAN_OPTS="-c -x c -I $DEPT_INC_DIR -Wall -Wswitch -Wno-deprecated-declarations -Wempty-body -Wconversion -Wreturn-type -Wparentheses -Wno-pointer-sign -Wno-format -Wuninitialized -Wunreachable-code -Wunused-function -Wunused-value -Wunused-variable -fno-strict-aliasing -fpic -fvisibility=hidden -fexceptions -std=c11"
CPP_LAN_OPTS="-c -x c++ -I $DEPT_INC_DIR -Wall -Wno-class-memaccess -Wno-reorder -Wswitch -Wno-deprecated-declarations -Wempty-body -Wconversion -Wreturn-type -Wparentheses -Wno-format -Wuninitialized -Wunreachable-code -Wunused-function -Wunused-value -Wunused-variable -fno-strict-aliasing -fpic -fthreadsafe-statics -fvisibility=hidden -fexceptions -frtti -std=c++14"
LINK_OPTS="-Wl,--no-undefined -Wl,-L$DEPT_LIB_DIR -L$DEPT_LIB_DIR -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -shared -Wl,-Bsymbolic"
RELEASE_CFG_OPTS="-g0 -O3 -fomit-frame-pointer -DNDEBUG"
DEBUG_CFG_OPTS="-g2 -gdwarf-2 -O0 -fno-omit-frame-pointer -DDEBUG -D_DEBUG"
if [ -d $HPSOCKET_LIB_TARGET_DIR ]; then
rm -rf $HPSOCKET_LIB_TARGET_DIR
fi
if [ -d $HPSOCKET4C_LIB_TARGET_DIR ]; then
rm -rf $HPSOCKET4C_LIB_TARGET_DIR
fi
# 編譯
do_compile $HPSOCKET_LIB_NAME $CFG_RELEASE
do_compile $HPSOCKET4C_LIB_NAME $CFG_RELEASE
if [ $WITH_DGBUG_LIB -eq 1 ]; then
do_compile $HPSOCKET_LIB_NAME $CFG_DEBUG
do_compile $HPSOCKET4C_LIB_NAME $CFG_DEBUG
fi
update_hp_def
}
do_compile()
{
_LIB_NAME=$1
_CFG_NAME=$2
parse_compile_args
do_compile_step_1
do_compile_step_2
do_compile_step_3
}
#這個函數大概就是遞歸編譯生成一堆*.o文件
do_comepile_file()
{
local _CMD="$CC $_LAN_OPTS $_FULL_FILE_NAME $_CFG_OPTS $_CL_OPTS -o $_OBJ_TARGET_DIR/ $_OBJ_NAME"
$_CMD
}
#這個函數連接.o生成.so庫
do_compile_step_2()
{
local _LIB_FILE_NAME="lib$_LIB_NAME$_LIB_NAME_SUFFIX.so"
local _SONAME_OPT="-Wl,-soname,$_LIB_FILE_NAME.$VER_MAJOR"
local _OBJ_TARGET_DIR=$_LIB_TARGET_DIR/$OBJ_DIR/$_CFG_NAME
local _OBJ_FILES=($(find $_OBJ_TARGET_DIR -name *.o | xargs ls))
local _CMD="$CC -o $_LIB_TARGET_DIR/$_LIB_FILE_NAME $LINK_OPTS $_SONAME_OPT ${_OBJ_FILES[@]} $_LN_OPTS"
echo "> $_CMD"
}
#調用 post-link.sh腳本打包.a庫
do_compile_step_3()
{
local _LIB_FILE_NAME="lib$_LIB_NAME$_LIB_NAME_SUFFIX"
local _LIB_PATH=$PACKAGE_PATH/$_LIB_TARGET_DIR
local _CMD="$SCRIPT_DIR/post-link.sh $_AR_FLAG $_LIB_PATH $_LIB_FILE_NAME $PLATFORM $_CFG_NAME $VER_MAJOR $VER_MINOR $VER_REVISE"
echo "> $_CMD"
$_CMD
}
install.sh就不說了。無非就是將庫拉倒系統目錄或者指定目錄,把.h拉到系統目錄中去。
parse_args "$@"
print_config
if [ $IS_UNINSTALL -eq 0 ]; then
do_install
else
do_uninstall
fi
ldconfig > /dev/null 2>&1
do_install()
{
mkdir -p $PREFIX_PATH/$DEST_LIB_DIR
# copy *.a
cp_lib_a $HPSOCKET_LIB_TARGET_DIR
cp_lib_a $HPSOCKET4C_LIB_TARGET_DIR
# copy *.so
cp_lib_so $HPSOCKET_LIB_TARGET_DIR
cp_lib_so $HPSOCKET4C_LIB_TARGET_DIR
mkdir -p $PREFIX_PATH/$DEST_INC_DIR
# copy include dir
cp_inc $INC_DIR $PREFIX_PATH/$DEST_INC_DIR
if [[ $INSTALL_DEMO -eq 1 && -d $DEM_DIR/$PLATFORM && "$(ls -A $DEM_DIR/$PLATFORM)" != "" ]]; then
# copy demo .exe files
mkdir -p $PREFIX_PATH/$DEST_BIN_DIR
cp_bin_exe
# copy demo ssl cert files
mkdir -p $PREFIX_PATH/$DEST_BIN_DIR/$DEST_CER_DIR
cp_bin_cert
fi
}
至此,庫的編譯就完成了。
demo的編譯
庫的應用代碼在demo目錄下,demo這裏是用sln組織的。
我之前用testecho-http這個demo來學習這個庫的使用。
但這裏有個大坑,我實際編譯的時候重寫成makefile,死活告訴我鏈接不到某幾個方法,但我已經加入庫了。
後來知道是爲什麼了,用
nm libsocket.so | grep 鏈接不到的函數名
發現前面的是小寫?然後幫助文檔裏有句話叫做
If the symbol is loacal(no-external), the symbol’s type is instead represented by the corresponding lowercase letter.
所以就是不能調用了哦。
然後這裏有幾種解決方法:
- 鏈接到.a可以解決,因爲.a是把.o打包
- 不要鏈接.so直接鏈接.o
- 修改代碼,換一種獲取類的方式