这篇文章的基础是上一篇对于将teamtalk中的线程池,连接池单独拆出来的讲解
不是说这个网络库会依赖线程池,连接池,而是上一篇文章中讲了一些base目录中的文件,并且这个网络库会依赖一些base目录里的文件, 文末会将所有文件一起打包以百度网盘链接的形式提供
teamtalk中的网络库主要包含的文件为:
netlib.h , netlib.cpp, EventDispatch.cpp, EventDispatch.h, BaseSocket.cpp, BaseSocket.h
测试案例使用cmake的方式组织
cmake代码:
cmake_minimum_required(VERSION 2.6)
project(test_netlib)
SET(EXECUTABLE_OUTPUT_PATH ./)
#AUX_SOURCE_DIRECTORY(../base SRC_LIST)
ADD_DEFINITIONS( -g -W -Wall -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DAC_HAS_INFO
-DAC_HAS_WARNING -DAC_HAS_ERROR -DAC_HAS_CRITICAL -DTIXML_USE_STL
-DAC_HAS_DEBUG -DLINUX_DAEMON -std=c++11 -DENCRYPT)
INCLUDE_DIRECTORIES(../base ../db_proxy_server)
#LINK_DIRECTORIES(./ ../base ../../base)
ADD_EXECUTABLE(client ./client.cpp )
ADD_EXECUTABLE(server ./server.cpp )
TARGET_LINK_LIBRARIES(client base slog)
TARGET_LINK_LIBRARIES(server base slog)
这里我使用teamtalk的网络库实现了一个双工通信效果的代码(客户端,服务端可以随意发消息)
客户端代码
#include "netlib.h"
#include "BaseSocket.h"
#include "EventDispatch.h"
#include <pthread.h>
#include <iostream>
using namespace std;
//因为netlib网络库的回调函数的参数形式就是这样
void* send_msg(void* handle) {
int fd = *(int*)handle;
while(1) {
CBaseSocket* pSocket = FindBaseSocket(fd);
string str;
cin >> str;
str += '\n';
int ret = netlib_send(fd, (void*)str.c_str(), str.length() + 1);
}
}
void imconn_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam)
{
switch(msg) {
case NETLIB_MSG_READ:
{
CBaseSocket* pSocket = FindBaseSocket(handle);
if(!pSocket) {
return ;
}
char buf[64] = {0};
int ret = netlib_recv(handle, buf, 64);
buf[ret] = '\0';
cout << buf ;
}
break;
case NETLIB_MSG_WRITE:
{
//
}
break;
}
}
int main() {
netlib_init();
net_handle_t handle = netlib_connect("127.0.0.1", 6666, imconn_callback, NULL);
CBaseSocket* pSocket = FindBaseSocket(handle);
if(!pSocket) {
return 0;
}
pSocket->SetState(SOCKET_STATE_CONNECTED);
pthread_t pt;
pthread_create(&pt, NULL, send_msg, &handle);
netlib_eventloop(10);
return 0;
}
服务端代码
#include "netlib.h"
#include "BaseSocket.h"
#include "EventDispatch.h"
#include <iostream>
#include <pthread.h>
using namespace std;
void* send_msg(void* handle) {
int fd = *(int*)handle;
while(1) {
CBaseSocket* pSocket = FindBaseSocket(fd);
string str;
cin >> str;
str += '\n';
int ret = netlib_send(fd, (void*)str.c_str(), str.length() + 1);
}
}
void imconn_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) {
switch(msg) {
case NETLIB_MSG_READ:
{
CBaseSocket* pSocket = FindBaseSocket(handle);
char buf[64] = {0};
int ret = netlib_recv(handle, buf, 64);
buf[ret] = '\0';
cout << buf;
//ret = netlib_send(handle, buf, ret);
//cout << ret << endl;
}
break;
case NETLIB_MSG_WRITE:
{
//
}
break;
}
}
void serv_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam)
{
if(msg == NETLIB_MSG_CONNECT) {
netlib_option(handle, NETLIB_OPT_SET_CALLBACK, (void*)imconn_callback);
CBaseSocket* pSocket = FindBaseSocket(handle);
if(!pSocket) {
return ;
}
pSocket->SetState(SOCKET_STATE_CONNECTED);
pthread_t pt;
pthread_create(&pt, NULL, send_msg, &handle);
}
}
int main() {
netlib_init();
int handle = netlib_listen("127.0.0.1", 6666, serv_callback, NULL);
netlib_eventloop(10);
return 0;
}
注意点:
在上一篇拆分线程池,连接池的文章的基础上,我这里只提供在上一篇的基础上新增的文件,若需要完整的可以把上一篇文章的链接内容下载下来,再将这一篇的添加上去。
怎么添加? 只需要把我最开始提到的那几个网络库需要的文件放到base目录中, 然后重新编译一下libbase.a这个库(怎么编译会在后边讲到,用cmake的方式,这个库是将base目录的所有文件编译而来),并且放到/usr/local/lib 或者 /urs/local/lib中, 而我写的客户端以及服务器放到与base目录的同级目录下。
目录结构如下:红框为新增的
上一篇没有讲解base目录中的源文件如何以cmake的方式管理,这里补充一下
在base目录中,touch CMakeList.txt
内容如下:
SET(PB_LIB_DIR ./pb/lib/linux)
SET(LIBRARY_OUTPUT_PATH ./)
ADD_DEFINITIONS( -g -W -Wall -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DAC_HAS_INFO
-DAC_HAS_WARNING -DAC_HAS_ERROR -DAC_HAS_CRITICAL -DTIXML_USE_STL
-DAC_HAS_DEBUG -DLINUX_DAEMON)
INCLUDE_DIRECTORIES(./ ../)
LINK_DIRECTORIES(./ ${PB_LIB_DIR} )
ADD_LIBRARY(base STATIC ${SRC_LIST1} )#*${SRC_LIST2} ${SRC_LIST3})
TARGET_LINK_LIBRARIES(base pthread slog protobuf-lite)
提示一下,libbase.a, libslog.so等库资源文件建议放到/usr/lib 或者 /usr/local/lib下
链接:https://pan.baidu.com/s/1g31MlF-OoeVmhKAc0FA1mg?pwd=qjj9
提取码:qjj9