前言
一个跨平台网络库
只所以写个,为了以后忘了,这里作为备份吧,都搭好多次了,换个机子搭一次
1:环境
分别在 ubuntu22 与 win10上编译下
libevent(2.1.12) download:https://libevent.org/
openssl(3.4.0) https://openssl-library.org/source/
2:ubuntu22
安装openssl
sudo apt-update
sudo apt-get install libevent-dev libssl-dev
其他安装安装说明进行就可以了,linux下比较简单
CMake (Unix)
$ mkdir build && cd build
$ cmake .. # Default to Unix Makefiles.
$ make
$ make verify # (optional)
make install 一般 我不执行,就放到这里就可以了,不想安装太到其他地方去
编译完后的
测试 代码 2015年写的,不过拿来重新编译下,跑下
main.cpp
// libeventtestrobot.cpp : ¶šÒå¿ØÖÆÌšÓŠÓóÌÐòµÄÈë¿Úµã¡£
//
#include "stdafx.h"
#include "robotlogic.h"
bool g_bJumpMap = false;
int main(int argc, char* argv[])
{
UINT32 u32GepMs = 300;
CHAR szIp[24] = "192.168.1.105";
INT32 n32Port = 4467;
INT32 n32Thread = 1;
INT32 n32RoleNum = 1;
switch (argc)
{
case 7:
{
g_bJumpMap = (bool)atoi(argv[6]);
}
case 6:
{
u32GepMs = atoi(argv[5]);
}
case 5:
{
n32RoleNum = atoi(argv[4]);
}
case 4:
{
n32Thread = atoi(argv[3]);
}
case 3:
{
n32Port = atoi(argv[2]);
}
case 2:
{
strncpy(szIp, argv[1], sizeof(szIp) - 1);
}
break;
}
CRobotLogic* pLogic = CRobotLogic::GetInstance();
if (pLogic->Init(szIp, n32Port, n32Thread, n32RoleNum, u32GepMs))
{
pLogic->Run();
pLogic->Fini();
}
int nQuit;
scanf("%d", &nQuit);
return 0;
}
IoThread.cpp
#include "stdafx.h"
#include "IoThread.h"
#include "logicThread.h"
#include "gsConnect.h"
#include "MsgInterface.h"
#include "MsgParser.h"
static void listen_thread_cb(struct evconnlistener *listener,
evutil_socket_t fd, struct sockaddr *addr, int socklen, void *args)
{
CNetWorkIoThread* pThread = (CNetWorkIoThread*)args;
if ( pThread )
{
pThread->onAccept(fd,addr,socklen);
}
}
void CNetWorkIoThread::onAccept(evutil_socket_t fd, struct sockaddr *addr, int socklen)
{
for(UINT8 i=0;i<10;i++)
{
// if(m_ArrayGs[i] && !m_ArrayGs[i]->isconnected())
// {
// printf("accept connect index=%d \n",i);
// m_ArrayGs[i]->setConnect(fd,addr,socklen);
// m_ArrayGs[i]->setGsID(i+1);
// m_ArrayGs[i]->setNetWorkIoThread(this);
// m_ArrayGs[i]->bindSocketBuffer(get_evbase());
// break;
// }
}
}
bool CNetWorkIoThread::Init(UINT32 u32QueueSize)
{
#ifdef WIN32
WSADATA wsa_data;
WSAStartup(0x0201, &wsa_data);
#endif
m_evbase = event_base_new();
if ( !m_evbase )
{
return false;
}
// ŽŽœšÏûÏ¢ÊäÈ뻺³åÇø
// m_pInputQueue = event_msgqueue_new();
// if ( NULL == m_pInputQueue )
// {
// return false;
// }
// if ( 0 != event_msgqueue_init(m_pInputQueue,1024,m_evbase,&msg_input_fn, (void*)this))
// {
// return false;
// }
// for(UINT8 i=0;i<10;i++)
// {
// m_ArrayGs[i] = new CGsConnect ;
// }
// ŽŽœšÏûÏ¢Êä³ö»º³åÇø
m_pOutputQueue = event_msgqueue_new();
if ( NULL == m_pOutputQueue )
{
return false;
}
if ( 0 != event_msgqueue_init(m_pOutputQueue,u32QueueSize,m_evbase,&msg_output_fn, (void*)this))
{
return false;
}
// ÌíŒÓ¶šÊ±ŽŠÀí£¬Ã¿Ã붚ʱŒì²âÁ¬œÓ׎̬¡£
struct timeval tv={10,0};
event_assign(&m_evTimer,get_evbase(),-1,EV_PERSIST,ev_thread_timer,this);
event_add(&m_evTimer,&tv);
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(m_szIp);
sin.sin_port = htons(m_n32Port);
m_listener = evconnlistener_new_bind(get_evbase(),listen_thread_cb,this, LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1,(struct sockaddr*)&sin,sizeof(sin));
if(NULL == m_listener)
return false;
// for(UINT8 i=0;i< 2;i++)
// {
// m_pDbLogicThread[i] = new CDBLogicThread((THREADID)i,ETHREAD_LOGIC);
// if(!m_pDbLogicThread[i]->init(this))
// {
// exit(1);
// }
// m_pDbLogicThread[i]->setIntervalMs(60*1000); //60ÃëÒ»ŽÎ
// if(0 == i) m_pDbLogicThread[i]->SetMainLogicThreadFlag(true); //ÂߌÖ÷Ïß³Ì
// m_pDbLogicThread[i]->start();
// }
return true;
}
bool CNetWorkIoThread::OnLoop()
{
if(get_evbase())
event_base_loop(get_evbase(),0);
return true;
}
void CNetWorkIoThread::ev_thread_timer(evutil_socket_t fd, short event, void *arg)
{
CNetWorkIoThread* pThread = (CNetWorkIoThread*)arg;
if ( pThread )
{
pThread->onTimer();
}
}
void CNetWorkIoThread::ev_thread_msg(const event_msg_t msg, void* args)
{
CNetWorkIoThread* pThread = (CNetWorkIoThread*)args;
if ( pThread )
{
//ev_thread_msg(msg,pThread);
//žùŸÝÏûÏ¢ÀàÐÍ·ÖÀà
///
host_msg_hd* pHostMsgHd = (host_msg_hd*)msg;
if (pHostMsgHd->m_t == host_mt_conn) {
conn_msg* pConnMsg = (conn_msg*)msg;
//pLogicIF->handle_conn_msg(pConnMsg);
// conn_msg_free(pConnMsg);
//logic_handle_conn_msg(pConnMsg, args);
} else {
net_msg* pNetMsg = (net_msg*)msg;
// pLogicIF->handle_logic_msg(pNetMsg);
// msg_free(msg);
//(*g_logic_handle_msg_fn)(pNetMsg, args);
}
/
}
}
void CNetWorkIoThread::msg_input_fn(const event_msg_t msg, void* args)
{
// io_thread* pThread = (io_thread*)args;
// logic_interface* pLogicIF = pThread->m_pParent->m_pLogicIF;
//
// host_msg_hd* pHostMsgHd = (host_msg_hd*)msg;
// if (pHostMsgHd->m_t == host_mt_conn) {
// conn_msg* pConnMsg = (conn_msg*)msg;
// pLogicIF->handle_conn_msg(pConnMsg);
// conn_msg_free(pConnMsg);
// //logic_handle_conn_msg(pConnMsg, args);
// } else {
// net_msg* pNetMsg = (net_msg*)msg;
// pLogicIF->handle_logic_msg(pNetMsg);
// msg_free(msg);
// }
}
//io Ïß³Ì
void CNetWorkIoThread::msg_output_fn(const event_msg_t msg, void* args)
{
CNetWorkIoThread* pNetWorkIoThread = (CNetWorkIoThread*)args;
host_msg_hd* pHostMsgHd = (host_msg_hd*)msg;
if( pHostMsgHd->m_t == host_mt_net )
{
net_msg* pNetMsg = (net_msg*)msg;
// CGsConnect* pGsConnect = pNetWorkIoThread->GetGsConnect(pHostMsgHd->m_connOid);
// if(pGsConnect&& pGsConnect->isconnected())
// {
// pGsConnect->sendmsg((my_net_msg_hd*)pNetMsg->m_body);
// }
msg_free(pNetMsg);
}else if(host_mt_roadcast == pHostMsgHd->m_t) //¹ã²¥
{
net_msg* pNetMsg = (net_msg*)msg;
pNetWorkIoThread->broadcastToGsMsg((my_net_msg_hd*)pNetMsg->m_body);
msg_free(pNetMsg);
}
// else if(pHostMsgHd->m_t == 3)
// {
// net_msg* pNetMsg = (net_msg*)msg;
//
// CGsConnect* pGsConnect = pNetWorkIoThread->GetGsConnect(pHostMsgHd->m_connOid);
// if(pGsConnect&& pGsConnect->isconnected())
// {
// pGsConnect->setConnectState(CONNECT_STATE_OK);
// }
// msg_free(pNetMsg);
// }
}
//ÂߌÏß³Ì
bool CNetWorkIoThread::sendThreadMsg(UINT8 u8GsId,CNetMsgHead* pHeadMsg)
{
///
if(pHeadMsg->wLen >= my_msg_max_len)
return false ;
net_msg* pHostMsg = NULL;
my_net_msg_hd* pMyMsg = NULL;
uint16 nSize = host_msg_hd_size+pHeadMsg->wLen+my_net_chk_size;
pHostMsg = (net_msg*)msg_alloc(nSize);
pHostMsg->m_hd.m_t = host_mt_net;
pHostMsg->m_hd.m_threadOid = 0;
pHostMsg->m_hd.m_connOid = u8GsId;
pMyMsg = (my_net_msg_hd*)pHostMsg->m_body;
pMyMsg->m_nLenChk = pHeadMsg->wLen;
memcpy(&pMyMsg->m_head, pHeadMsg, pHeadMsg->wLen);
if (event_msgqueue_push(m_pOutputQueue, pHostMsg) != 0) {
msg_free(pHostMsg);
return false;
}
return true;
}
bool CNetWorkIoThread::broadcastThreadMsg(CNetMsgHead* pHeadMsg)
{
///
if(pHeadMsg->wLen >= my_msg_max_len)
return false ;
net_msg* pHostMsg = NULL;
my_net_msg_hd* pMyMsg = NULL;
uint16 nSize = host_msg_hd_size+pHeadMsg->wLen+my_net_chk_size;
pHostMsg = (net_msg*)msg_alloc(nSize);
pHostMsg->m_hd.m_t = host_mt_roadcast;
pHostMsg->m_hd.m_threadOid = 0;
pHostMsg->m_hd.m_connOid = 0xFF;
pMyMsg = (my_net_msg_hd*)pHostMsg->m_body;
pMyMsg->m_nLenChk = pHeadMsg->wLen;
memcpy(&pMyMsg->m_head, pHeadMsg, pHeadMsg->wLen);
if (event_msgqueue_push(m_pOutputQueue, pHostMsg) != 0) {
msg_free(pHostMsg);
return false;
}
return true;
}
void CNetWorkIoThread::broadcastToGsMsg(my_net_msg_hd* pMsg)
{
for(UINT8 i= 0;i<10;i++)
{
// if(m_ArrayGs[i] && m_ArrayGs[i]->isconnected() && CONNECT_STATE_OK == m_ArrayGs[i]->getConnectState())
// {
// m_ArrayGs[i]->sendmsg(pMsg) ;
// }
}
}
void CNetWorkIoThread::onTimer()
{
for(UINT8 i= 0;i<10;i++)
{
// if(m_ArrayGs[i] && m_ArrayGs[i]->isconnected())
// {
//
// }
}
}
cmakefile
#1.cmake verson,指定cmake版本
cmake_minimum_required(VERSION 2.6)
#2.project name,指定项目的名称,一般和项目的文件夹名称对应
PROJECT(libeventtestrobot)
#3.head file path,头文件目录
INCLUDE_DIRECTORIES(
include
)
#4.source directory,源文件目录
AUX_SOURCE_DIRECTORY(src DIR_SRCS)
#5.set environment variable,设置环境变量,编译用到的源文件全部都要放到这里,否则编译能够通过,但是执行的时候会出现各种问题,比如"symbol lookup error xxxxx , undefined symbol"
SET(TEST_MATH
${DIR_SRCS}
)
SET(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
#指定查找路径
SET(Libevent_DIR /home/ubuntu/code/libevent/build)
#find_package(Libevent PATHS /home/ubuntu/code/libevent/build)
find_package(Libevent CONFIG REQUIRED)
#利用寻找之后的变量
if(NOT Libevent_FOUND)
message("error: connot found Libevent moudle")
else()
message(STATUS "found Libevent moudle")
endif()
# Requires OpenCV
# FIND_PACKAGE( OpenCV 4.0.0 REQUIRED )
#FIND_PACKAGE( OpenCV 4.0.0 REQUIRED )
MESSAGE("Libevent version : ${Libevent_VERSION}")
#message(STATUS "include path: ${LIBEVENT_INCLUDE_DIRS}")
#MESSAGE("Libevent_INCLUDE : ${Libevent_INCLUDE_DIRS}")
#MESSAGE("Libevent_LIB_DIR : ${Libevent_LIB_DIR}")
# LIBEVENT_FOUND - true if libevent and all required components found on the system
# LIBEVENT_xxx_FOUND - true if component xxx(see available components) found on the system
# LIBEVENT_VERSION - libevent version in format Major.Minor.Patch
# LIBEVENT_INCLUDE_DIRS - directories where libevent header is located.
# LIBEVENT_INCLUDE_DIR - same as DIRS
# LIBEVENT_LIBRARIES - libevent library to link against.
# LIBEVENT_LIBRARY - same as LIBRARIES
#set(${LIBEVENT_INCLUDE_DIR} /home/ubuntu/code/libevent/build/include)
#set(${LIBEVENT_LIBRARIES} /home/ubuntu/code/libevent/build/lib)
MESSAGE("Libevent_INCLUDE : ${LIBEVENT_INCLUDE_DIR}")
MESSAGE("Libevent_LIB_DIR : ${LIBEVENT_LIBRARIES}")
#临时增加到PATH上去
include_directories(${LIBEVENT_INCLUDE_DIR})
link_directories(${LIBEVENT_LIBRARIES})
#6.add executable file,添加要编译的可执行文件
ADD_EXECUTABLE(${PROJECT_NAME} ${TEST_MATH})
#7.add link library,添加可执行文件所需要的库,比如我们用到了libm.so(命名规则:lib+name+.so),就添加该库的名称
#TARGET_LINK_LIBRARIES(${PROJECT_NAME} m)
#TARGET_LINK_LIBRARIES(${PROJECT_NAME} libevent.so)
#TARGET_LINK_LIBRARIES(${PROJECT_NAME} libevent_pthreads.so)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LIBEVENT_LIBRARIES} Threads::Threads)
#TARGET_LINK_LIBRARIES(${PROJECT_NAME} Threads::Threads)
#TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread)
注意点
跑起来没问题,就是server还没开
3:win10
perl (5.40.0.1 Portable zip) download :https://strawberryperl.com/
下载便携式版,省事,自己配置到path里就行
cmake(3.31.2) https://github.com/Kitware/CMake/releases/ 这里选择的 cmake-3.31.2-windows-x86_64.zip 解压后配到到path里
nasm(nasm-2.16.03-win64.zip) https://www.nasm.us/pub/nasm/releasebuilds/2.16.03/win64/
这里下载的 是 nasm-2.16.03-win64.zip 个人不喜欢下安装版
一样配到到path 里
vs2022 已经安装,自行安装
nmake c1 == vs2022 自带
在 D:\soft_install\vs\2022\Community\VC\Tools\MSVC\14.41.34120\bin 里,自行选择版本
加到了path里
编译openssl 按说明编译就行
用vs2022下的 x86_x64 Cross Tools Command Prompt for VS 2022 不要用 cmd
指定安装路径 perl Configure VC-WIN64A --prefix=D:\code\lib\openssl\lib
–prefix=D:\code\lib\openssl\lib 不用就是默认路径 C:\Program Files (x86)\OpenSSL
*如果只之前指定了其他方式或目录 ,删了,重解压,重新来一次,不然可能会出现意想不到的问题
直接指定 D:\soft_install\vs\2022\Community\VC\Tools\MSVC\14.41.34120\bin\Hostx64\x64\nmake
单核编译,很慢,10来分钟
D:\soft_install\vs\2022\Community\VC\Tools\MSVC\14.41.34120\bin\Hostx64\x64\nmake install
安装到指定的目录下
编译libevent
md build
cd build
cmake -G “Visual Studio 17 2022” …
start libevent.sln #直接用 vs 打开 libevent.sln 就可以了 -++++++++++++++++++++++±+
cmakefile 需要修改下,指定openssl 库目录(因为没配置到 PATH里)
cmakefile
#843 line 原文件的位置,下面部分修改了下
if (NOT EVENT__DISABLE_OPENSSL)
#SET(OpenSSL_DIR D:/code/lib/openssl)
#set(OpenSSL_DIR "D:/code/lib/openssl/lib")
set(OPENSSL_ROOT_DIR "D:/code/lib/openssl/lib")#为了能找到OPENSSL 20241213 eh
#message("322223")
find_package(OpenSSL REQUIRED)
#set(${LIBEVENT_INCLUDE_DIR} "D:/code/lib/openssl/lib/include") #直接指定 20241213 eh
#set(${OPENSSL_LIBRARIES} "D:/code/lib/openssl/lib/lib") #直接指定 20241213 eh
set(EVENT__HAVE_OPENSSL 1)
#message("3333333")
message(STATUS "OpenSSL include: ${OPENSSL_INCLUDE_DIR}")
message(STATUS "OpenSSL lib: ${OPENSSL_LIBRARIES}")
include_directories(${OPENSSL_INCLUDE_DIR})
list(APPEND SRC_OPENSSL bufferevent_openssl.c)
list(APPEND HDR_PUBLIC include/event2/bufferevent_ssl.h)
list(APPEND LIB_APPS ${OPENSSL_LIBRARIES})
endif()
编译lib OK
pthread(RELEASE 3.0.3.1) download: https://github.com/GerHobbelt/pthread-win32?tab=readme-ov-file
编译
md build
cd build
cmake …
#D:\code\lib\pthread-win32-master\build>cmake …
测试 linux 下同样代码
稍微修改了下,windows 增加 网络库
event.lib copy rename libevent.so.lib
预编译处理 增加 _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS=1
cmakefile 也修改了下
#1.cmake verson,指定cmake版本
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
cmake_minimum_required(VERSION 2.6)
elseif(CMAKE_SYSTEM_NAME MATCHES "Windows")
cmake_minimum_required(VERSION 3.31)
endif()
#2.project name,指定项目的名称,一般和项目的文件夹名称对应
PROJECT(libeventtestrobot)
#3.head file path,头文件目录
INCLUDE_DIRECTORIES(
include
)
#4.source directory,源文件目录
AUX_SOURCE_DIRECTORY(src DIR_SRCS)
#5.set environment variable,设置环境变量,编译用到的源文件全部都要放到这里,否则编译能够通过,但是执行的时候会出现各种问题,比如"symbol lookup error xxxxx , undefined symbol"
SET(TEST_MATH
${DIR_SRCS}
)
#######################################################################
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
message(STATUS "Running on Linux操作系统")
# 在这里添加适用于Linux的操作系统的特定配置
SET(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
elseif(CMAKE_SYSTEM_NAME MATCHES "Windows")
message(STATUS "Running on Windows操作系统")
# 在这里添加适用于Windows的操作系统的特定配置
set(pthreads4w_DIR "D:/code/lib/pthread-win32-master/build")
find_package(pthreads4w CONFIG REQUIRED)
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
message(STATUS "Running on macOS/iOS操作系统")
# 在这里添加适用于macOS/iOS的操作系统的特定配置
else()
message(STATUS "Running on an unknown operating system")
# 在这里添加适用于其他操作系统的通用配置
endif()
########################################################################
######################################################
SET(Libevent_DIR D:/code/lib/libevent/build)
#find_package(Libevent PATHS /home/ubuntu/code/libevent/build)
find_package(Libevent CONFIG REQUIRED)
#利用寻找之后的变量
if(NOT Libevent_FOUND)
message("error: connot found Libevent moudle")
else()
message(STATUS "found Libevent moudle")
endif()
# Requires OpenCV
# FIND_PACKAGE( OpenCV 4.0.0 REQUIRED )
#FIND_PACKAGE( OpenCV 4.0.0 REQUIRED )
MESSAGE("Libevent version : ${Libevent_VERSION}")
#message(STATUS "include path: ${LIBEVENT_INCLUDE_DIRS}")
#MESSAGE("Libevent_INCLUDE : ${Libevent_INCLUDE_DIRS}")
#MESSAGE("Libevent_LIB_DIR : ${Libevent_LIB_DIR}")
# LIBEVENT_FOUND - true if libevent and all required components found on the system
# LIBEVENT_xxx_FOUND - true if component xxx(see available components) found on the system
# LIBEVENT_VERSION - libevent version in format Major.Minor.Patch
# LIBEVENT_INCLUDE_DIRS - directories where libevent header is located.
# LIBEVENT_INCLUDE_DIR - same as DIRS
# LIBEVENT_LIBRARIES - libevent library to link against.
# LIBEVENT_LIBRARY - same as LIBRARIES
#set(${LIBEVENT_INCLUDE_DIR} /home/ubuntu/code/libevent/build/include)
#set(${LIBEVENT_LIBRARIES} /home/ubuntu/code/libevent/build/lib)
MESSAGE("Libevent_INCLUDE : ${LIBEVENT_INCLUDE_DIR}")
MESSAGE("Libevent_LIB_DIR : ${LIBEVENT_LIBRARIES}")
#临时增加到PATH上去
include_directories(${LIBEVENT_INCLUDE_DIR})
#link_directories(${LIBEVENT_LIBRARIES}) #手动加
#####################################################
#6.add executable file,添加要编译的可执行文件
ADD_EXECUTABLE(${PROJECT_NAME} ${TEST_MATH})
#7.add link library,添加可执行文件所需要的库,比如我们用到了libm.so(命名规则:lib+name+.so),就添加该库的名称
#TARGET_LINK_LIBRARIES(${PROJECT_NAME} m)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} libevent.so)
#TARGET_LINK_LIBRARIES(${PROJECT_NAME} libevent_pthreads.so)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
TARGET_LINK_LIBRARIES(${PROJECT_NAME} Threads::Threads)
elseif(CMAKE_SYSTEM_NAME MATCHES "Windows")
#TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthreads4w::pthreadVSE3)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthreadVSE3)
endif()
#TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread)
#直接传参数 cmake -DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a
#直接传参数 cmake -DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a
记得把event.dll 拷贝到 运行目录
4:如果觉得有用,麻烦点个赞,加个收藏