主函数代码如下
#include <ip/client/tcp_client.h>
#include "client_message_factory.h"
#include <iostream>
#include <utils.h>
#include <thread>
#include <chrono>
using namespace std;
using namespace klicen::asio::ip;
int main()
{
// 默认创建线程池的大小为4。
//IoServicePool::singleton::Create(4);
auto tcp_client = make_shared <TcpClient>();
tcp_client->SetMessageFactory(shared_ptr <klicen::asio::ip::MessageFactory>(new ClientMessageFactory));
tcp_client->Connect("127.0.0.1", 1234);
thread t([]() { IoServicePool::singleton::GetInstance()->Run(); });
t.detach();
while (true)
{
cout << "please input send server string(enter to end): ";
char buffer[1024];
cin >> buffer;
tcp_client->AsyncWrite(ToNetwork(buffer));
this_thread::sleep_for(chrono::seconds(1));
//cin.getline(buffer, size(buffer));
}
return EXIT_SUCCESS;
}
主函数中只需要实例化TcpClient类(TcpClient类构造函数提供参数auto_reconnect,默认为true,自动发起异步重连),设置TcpClient类的MessageFactory。IoServicePool如果没有调用create函数, 默认创建线程池的大小为4。一定记得在最后调用IoServicePool类的run函数,启动io线程池。本例使用的是Connect函数(同步连接),也可以使用AsyncConnect发起异步连接。
client_message_factory.h代码如下
#pragma once
#include <ip/message_factory.h>
#include <utils.h>
class ClientMessageFactory : public klicen::asio::ip::MessageFactory
{
using klicen::asio::ip::MessageFactory::MessageFactory;
private:
virtual bool IsConsumedForRead(const uint8_t* buffer, const size_t& length, size_t& deal_length, bool& has_package) override final;
virtual bool HandleRead(const uint8_t* buffer, const size_t& length, string& response) override final;
};
需要实现IsConsumedForRead、HandleRead等虚函数。IsConsumedForRead函数是判断数据包是否接受完成,HandleRead表示收到完整数据包返回个用户层处理(可在TcpServer类构造函数设置参数read_work_threads,构造独立的线程池来供业务层处理网络层读取到的数据,防止阻塞网络层的读事件)。
client_message_factory.cpp代码如下
#include "client_message_factory.h"
#include <boost/asio.hpp>
bool ClientMessageFactory::IsConsumedForRead(const uint8_t* buffer, const size_t& length, size_t& deal_length, bool& has_package)
{
uint32_t content_length = 0;
if (length < 4 || (content_length = boost::asio::detail::socket_ops::network_to_host_long(*reinterpret_cast <const uint32_t *>(buffer))) > length - 4)
{
has_package = true;
return false;
}
deal_length = 4 + content_length;
return true;
}
bool ClientMessageFactory::HandleRead(const uint8_t* buffer, const size_t& length, string& response)
{
printf("receive server data: %s\n", ToHost(buffer, length).content.c_str());
return true;
}
设置has_package标识的同时返回false,代表数据不是一个完整的包,还有后续数据包。返回true的时候,记得设置deal_length参数哦。
运行结果如下
connect to 127.0.0.1:1234
connection is successful
please input send server string(enter to end): 2
receive server data: server response data
please input send server string(enter to end): 3
receive server data: server response data
please input send server string(enter to end): 4
receive server data: server response data
please input send server string(enter to end):
表示连接服务器成功,收到服务器3条应答信息。“please input send server string”后面是等待你输入发往客户端的字符串,用enter键代表输入结束。 receive server data后面就是具体的服务器发送的数据内容。是不是很简单,,欢迎大家使用。
资源下载
git地址为:https://github.com/wangziwen333/happy-ip
boost库1.63版本头文件与库文件下载路径:https://download.csdn.net/download/wang19840301/10665704
windows编译参数
cmake .. -LA -DBOOST_INCLUDE_DIR='E:\git\boost\include' -DBOOST_LIB_DIR='E:\git\boost\lib\win32_debug' -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS_DEBUG="/MTd /Zi /Ob0 /Od /RTC1" -DBUILD_EXAMPLES=ON
linux编译参数
cmake .. -LA -DBOOST_INCLUDE_DIR='/mnt/e/git/boost/include' -DBOOST_LIB_DIR='/mnt/e/git/boost/lib/linux_debug' -DCMAKE_BUILD_TYPE=Debug -DBUILD_EXAMPLES=ON