Boost 利用ASIO实现一个跨平台的远控程序,该远控支持保存套接字,当有套接字连入时,自动存储到map容器,需要时直接获取特定套接字实现通信。
客户端代码:
#ifdef _MSC_VER
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#define _WIN32_WINNT 0x0601
#endif
#include <iostream>
#include <boost\array.hpp>
#include <boost\bind.hpp>
#include <boost\noncopyable.hpp>
#include <boost\asio.hpp>
using namespace std;
using namespace boost::asio;
using namespace boost::asio::ip;
int main(int argc, char* argv[])
{
try
{
io_service service;
tcp::socket socket(service);
boost::system::error_code error;
tcp::endpoint endpoint(address_v4::from_string("127.0.0.1"), 10000);
socket.connect(endpoint, error);
while (1)
{
// 客户端接收数据包
boost::array<char, 4096> buffer = { 0 };
socket.read_some(boost::asio::buffer(buffer), error);
std::cout << "接收服务端数据: " << buffer.data() << std::endl;
// 客户端发送数据
socket.write_some(boost::asio::buffer("cliend message"));
}
}
catch (exception& e){
string s = e.what();
}
std::system("pause");
return 0;
}
服务端代码1:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
// 存储当前客户端的ID号
std::vector<int> tcp_client_id;
class EventHandler : public TcpServer::IEventHandler
{
public:
// 客户端连接时触发
virtual void ClientConnected(int clientId)
{
// 将登录客户端加入到容器中
// cout << "客户端ID: " << clientId << endl;
tcp_client_id.push_back(clientId);
}
// 客户端退出时触发
virtual void ClientDisconnect(int clientId)
{
// 将登出的客户端从容器中移除
// cout << "客户端ID: " << clientId << endl;
vector<int>::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)
{
// cout << "客户端ID: " << clientId << endl;
std::cout <<"返回数据: " << data << " 返回长度: " << length << std::endl;
}
};
// 同步发送数据到指定的线程中
void send_message(TcpServer &tcpServer, int clientId, std::string message)
{
BYTE* buf = new BYTE(message.length() + 1);
// std::cout << "长度: " << message.length() << std::endl;
int i;
for (int i = 0; i<message.length(); i++)
{
buf[i] = message.at(i);
}
std::cout << "发送数据: " << buf << std::endl;
tcpServer.Send(clientId, buf, message.length());
}
int main(int argc, char* argv[])
{
std::map<int, std::string> ptr;
TcpServer tcpServer(10, 10000);
EventHandler eventHandler;
tcpServer.AddEventHandler(&eventHandler);
string flag;
while (1)
{
_sleep(1000);
std::cout << "输入命令: ";
cin >> flag;
// 发送一条测试消息
if (flag == "send")
{
int the_id;
std::cout << "输入发送序号: ";
std::cin >> the_id;
send_message(tcpServer, the_id, "hello lyshark");
}
// 输出当前在线的IP地址列表
else if (flag == "list")
{
std::cout << "--------------------------------------------" << std::endl;
for (int x = 0; x < tcp_client_id.size(); x++)
{
std::cout << "客户端序号: " << tcp_client_id[x]
<< " 客户端IP: " << tcpServer.GetRemoteAddress(tcp_client_id[x])
<< std::endl;
}
std::cout << "--------------------------------------------" << std::endl;
}
}
return 0;
}
客户端2: 增加异步连接超时机制。
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/array.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/noncopyable.hpp>
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;
}
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);
// 循环验证是否在线
while (1)
{
// 验证是否连接成功,并定义超时时间为3秒
if (hander.aysnc_connect(ep, 5000))
{
io.run();
std::cout << "已连接到服务端." << std::endl;
// 循环接收命令
while (1)
{
// 客户端接收数据包
boost::array<char, 4096> buffer = { 0 };
socket.read_some(boost::asio::buffer(buffer), error);
// std::cout << "接收服务端数据: " << buffer.data() << std::endl;
// 判断收到的命令是否为GetCPU
if (strncmp(buffer.data(), "GetCPU", strlen("GetCPU")) == 0)
{
std::cout << "获取CPU参数并返回给服务端." << std::endl;
socket.write_some(boost::asio::buffer("CPU: 15 %"));
}
// 判断收到的命令是否为终止程序
if (strncmp(buffer.data(), "Exit", strlen("Exit")) == 0)
{
std::cout << "终止客户端." << std::endl;
return 0;
}
}
}
else
{
std::cout << "连接失败,正在重新连接." << std::endl;
}
}
}
catch (...)
{
return false;
}
std::system("pause");
return 0;
}
客户端3:增加心跳检测:
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/array.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/noncopyable.hpp>
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);
// 循环验证是否在线
while (1)
{
// 验证是否连接成功,并定义超时时间为5秒
if (hander.aysnc_connect(ep, 5000))
{
io.run();
std::cout << "已连接到服务端." << std::endl;
// 循环接收命令
while (1)
{
// 验证地址端口是否开放,默认等待5秒
bool is_open = hander.port_is_open("127.0.0.1", 10000,5000);
// 客户端接收数据包
boost::array<char, 4096> 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 << "获取CPU参数并返回给服务端." << std::endl;
socket.write_some(boost::asio::buffer("CPU: 15 %"));
}
// 判断收到的命令是否为GetMEM
if (strncmp(buffer.data(), "GetMEM", strlen("GetMEM")) == 0)
{
std::cout << "获取MEM参数并返回给服务端." << std::endl;
socket.write_some(boost::asio::buffer("MEM: 78 %"));
}
// 判断收到的命令是否为终止程序
if (strncmp(buffer.data(), "Exit", strlen("Exit")) == 0)
{
std::cout << "终止客户端." << std::endl;
return 0;
}
}
else
{
}
}
}
else
{
std::cout << "连接失败,正在重新连接." << std::endl;
}
}
}
catch (...)
{
return false;
}
std::system("pause");
return 0;
}