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; }