Boost 利用ASIO框架实现一个跨平台的反向远控程序,该远控支持保存套接字,当有套接字连入时,自动存储到map容器,当客户下线时自动从map容器中移除,当我们需要与特定客户端通信时,只需要指定客户端ID号即可。
AsyncTcpServer
服务端首先定义CEventHandler
类并继承自CAsyncTcpServer::IEventHandler
接口,该类内需要我们实现三个方法,方法ClientConnected
用于在客户端连接时触发,方法ClientDisconnect
则是在登录客户端离开时触发,而当客户端有数据发送过来时则ReceiveData
方法则会被触发。
方法ClientConnected
当被触发时自动将clientId
客户端Socket套接字放入到tcp_client_id
全局容器内存储起来,而当ClientDisconnect
客户端退出时,则直接遍历这个迭代容器,找到序列号并通过tcp_client_id.erase
将其剔除;
// 客户端连接时触发
virtual void ClientConnected(int clientId)
{
// 将登录客户端加入到容器中
tcp_client_id.push_back(clientId);
}
// 客户端退出时触发
virtual void ClientDisconnect(int clientId)
{
// 将登出的客户端从容器中移除
vector::iterator item = find(tcp_client_id.begin(), tcp_client_id.end(), clientId);
if (item != tcp_client_id.cend())
tcp_client_id.erase(item);
}
而ReceiveData
一旦收到数据,则直接将其打印输出到屏幕,即可实现客户端参数接收的目的;
// 客户端获取数据
virtual void ReceiveData(int clientId, const BYTE* data, size_t length)
{
std::cout
相对于接收数据而言,发送数据则是通过同步的方式进行,当我们需要发送数据时,只需要将数据字符串放入到一个BYTE*
字节数组中,并在调用tcpServer.Send
时将所需参数,套接字ID,缓冲区Buf数据,以及长度传递即可实现将数据发送给指定的客户端;
// 同步发送数据到指定的线程中
void send_message(CAsyncTcpServer& tcpServer, int clientId, std::string message, int message_size)
{
// 获取长度
BYTE* buf = new BYTE(message_size + 1);
memset(buf, 0, message_size + 1);
for (int i = 0; i
AsyncTcpClient
客户端首先我们封装实现AsyncConnect
类,该类内主要实现两个功能,其中aysnc_connect
方法用于实现异步连接到服务端,而port_is_open
方法则用于验证服务器特定端口是否开放,在调用boost::bind
绑定套接字时传入&AsyncConnect::timer_handle
设置一个超时等待时间。
进入到main
主函数中,通过while
循环让程序可以一直运行下去,并通过hander.aysnc_connect(ep, 5000)
每隔5秒验证是否连接成功,如果连接了则进入内循环,通过hander.port_is_open("127.0.0.1", 10000, 5000)
验证端口是否开放,这主要是为了保证服务端断开后客户端依然能够跳转到外部循环继续等待服务端上线。
案例演示
首先运行服务端程序,接着运行多个客户端,即可实现自动上线;
当用户需要通信时,只需要指定id序号到指定的Socket套接字编号即可;
源代码
服务端代码
// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com
#include "AsyncTcpServer.h"
#include
#include
#include
#include
using namespace std;
// 存储当前客户端的ID号
std::vector tcp_client_id;
// 输出特定长度的行
void PrintLine(int line)
{
for (int x = 0; x ::iterator item = find(tcp_client_id.begin(), tcp_client_id.end(), clientId);
if (item != tcp_client_id.cend())
tcp_client_id.erase(item);
}
// 客户端获取数据
virtual void ReceiveData(int clientId, const BYTE* data, size_t length)
{
std::cout sep(", --");
typedef boost::tokenizer<:char_separator>> CustonTokenizer;
CustonTokenizer tok(command, sep);
// 将分词结果放入vector链表
std::vector<:string> vecSegTag;
for (CustonTokenizer::iterator beg = tok.begin(); beg != tok.end(); ++beg)
{
vecSegTag.push_back(*beg);
}
// 解析 [shell] # ShowSocket
if (vecSegTag.size() == 1 && vecSegTag[0] == "ShowSocket")
{
PrintLine(80);
printf("客户ID t 客户IP地址 t 客户端口 n");
PrintLine(80);
for (int x = 0; x
客户端代码
// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using boost::asio::ip::tcp;
// 异步连接地址与端口
class AsyncConnect
{
public:
AsyncConnect(boost::asio::io_service& ios, tcp::socket &s)
:io_service_(ios), timer_(ios), socket_(s) {}
// 异步连接
bool aysnc_connect(const tcp::endpoint &ep, int million_seconds)
{
bool connect_success = false;
// 异步连接,当连接成功后将触发 connect_handle 函数
socket_.async_connect(ep, boost::bind(&AsyncConnect::connect_handle, this, _1, boost::ref(connect_success)));
// 设置一个定时器 million_seconds
timer_.expires_from_now(boost::posix_time::milliseconds(million_seconds));
bool timeout = false;
// 异步等待 如果超时则执行 timer_handle
timer_.async_wait(boost::bind(&AsyncConnect::timer_handle, this, _1, boost::ref(timeout)));
do
{
// 等待异步操作完成
io_service_.run_one();
// 判断如果timeout没超时,或者是连接建立了,则不再等待
} while (!timeout && !connect_success);
timer_.cancel();
return connect_success;
}
// 验证服务器端口是否开放
bool port_is_open(std::string address, int port, int timeout)
{
try
{
boost::asio::io_service io;
tcp::socket socket(io);
AsyncConnect hander(io, socket);
tcp::endpoint ep(boost::asio::ip::address::from_string(address), port);
if (hander.aysnc_connect(ep, timeout))
{
io.run();
io.reset();
return true;
}
else
{
return false;
}
}
catch (...)
{
return false;
}
}
private:
// 如果连接成功了,则 connect_success = true
void connect_handle(boost::system::error_code ec, bool &connect_success)
{
if (!ec)
{
connect_success = true;
}
}
// 定时器超时timeout = true
void timer_handle(boost::system::error_code ec, bool &timeout)
{
if (!ec)
{
socket_.close();
timeout = true;
}
}
boost::asio::io_service &io_service_;
boost::asio::deadline_timer timer_;
tcp::socket &socket_;
};
int main(int argc, char * argv[])
{
try
{
boost::asio::io_service io;
tcp::socket socket(io);
AsyncConnect hander(io, socket);
boost::system::error_code error;
tcp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 10000);
// 循环验证是否在线
go_: while (1)
{
// 验证是否连接成功,并定义超时时间为5秒
if (hander.aysnc_connect(ep, 5000))
{
io.run();
std::cout buffer = { 0 };
// 如果在线则继续执行
if (is_open == true)
{
socket.read_some(boost::asio::buffer(buffer), error);
// 判断收到的命令是否为GetCPU
if (strncmp(buffer.data(), "GetCPU", strlen("GetCPU")) == 0)
{
std::cout
项目地址
https://github.com/lyshark/BoostAsyncSocket
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net