# CPPProject-NetworkProber **Repository Path**: krenedu/CPPProject-NetworkProber ## Basic Information - **Project Name**: CPPProject-NetworkProber - **Description**: CPPProject-NetworkProber - **Primary Language**: C++ - **License**: Not specified - **Default Branch**: zhxl - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-05-25 - **Last Updated**: 2026-02-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README #include #include #include // // // #include "proto/sample.pb.h" #include "proto/greeter.pb.h" #include "proto/greeter.grpc.pb.h" // #include #include #include #include #include #include #include #include #include #include class RpcGreeterService : public Greeter::Service { public: /** * * @param context * @param request * @param response * @return */ grpc::Status sayHello(grpc::ServerContext *context, const Request *request, Response *response) override { std::cout << request->name() << std::endl; std::ostringstream message; message << "sayHello Name: " << request->name() << std::endl; response->set_message(message.str()); return grpc::Status::OK; } ~RpcGreeterService() { } }; // // void runClient() // { // // 1 connect to server // std::shared_ptr channel = grpc::CreateChannel("127.0.0.1:50052", grpc::InsecureChannelCredentials()); // // // 2 generate a stub according the channel // std::unique_ptr stub = Greeter::NewStub(channel); // // // 3 create params // // 3.1 context // grpc::ClientContext clientContext; // // 3.2 request // Request request; // request.set_name("hello"); // // 3.3 response // Response response; // // // 4 send a service call // grpc::Status status = stub->sayHello(&clientContext, request, &response); // // // 5 handle response // // 5.1 handle error resp // if (!status.ok()) { // std::cerr << status.error_code() << ": " << status.error_message() << std::endl; // return; // } // // // 5.2 handle success resp // std::cout << response.message() << std::endl; // // // Greeter greeter; // // // // Developer developer; // // // // developer.set_name("zhang san"); // // // // std::cout << developer.name() << std::endl; // // // Employee employee; // // // // employee.set_age(20); // // // network_prober::logger::DebugLogger::getInstance(); // } // void createServer() // { // // 1 create a server builder // grpc::ServerBuilder builder; // // 2 config the server builder // builder.AddListeningPort("0.0.0.0:50052", grpc::InsecureServerCredentials()); // // // 3 register a service // RpcGreeterService service; // builder.RegisterService(&service); // // // 4 start the server // std::unique_ptr serverPtr = builder.BuildAndStart(); // serverPtr->Wait(); // // } /** * 接收到数据包时调用 * @param user_data * @param pkthdr * @param packet */ // void packet_handler(u_char *user_data, const struct pcap_pkthdr *pkthdr, const u_char *packet) // { // // 数据包处理函数 // printf("Received packet: length: %d\n", pkthdr->len); // } // int libPcapTest() { // pcap_t* pcapHandle = NULL; // // char errbuf[PCAP_ERRBUF_SIZE] = ""; // // char* pNetInterfaceName = NULL; // // pcap_if_t* allDevs = NULL; // // // 查找本地设备列表 // if (pcap_findalldevs(&allDevs, errbuf) == -1) { // perror("pcap_lookupdev"); // return -1; // } // // // 遍历每个设备,输出设备信息 // for (pcap_if_t *d=allDevs; d!=NULL; d=d->next) { // printf("%s - %s\n", d->name, (d->description) ? d->description : "No description available"); // } // // // 打开选择的适配器 // if ((pcapHandle = pcap_open_live(allDevs[0].name, BUFSIZ, 1, 1000, errbuf)) == NULL) { // fprintf(stderr,"Couldn't open device %s: %s\n", allDevs[0].name, errbuf); // exit(1); // } // // // 从打开的适配器捕获数据包 // if (pcap_loop(pcapHandle, 0, packet_handler, NULL) < 0) { // fprintf(stderr, "\npcap_loop() failed: %s\n", pcap_geterr(pcapHandle)); // exit(1); // } // // pcap_freealldevs(allDevs); // } // int packetTest() // { // // 读取一个数据包文件 // pcpp::PcapFileReaderDevice reader("/home/twetec/Desktop/workspace-NetworkProber/repository/CPPProject-NetworkProber/NetworkProber/network_prober/1_packet.pcap"); // if (!reader.open()) { // std::cerr << "Error opening the pcap file" << std::endl; // return 1; // } // // // 从数据包文件中读取一个数据包 // pcpp::RawPacket rawPacket; // if (!reader.getNextPacket(rawPacket)) { // std::cerr << "Couldn't read the first packet in the file" << std::endl; // return 1; // } // // // 将数据包中的二进制数据解析为对应的网络协议数据 // pcpp::Packet parsedPacket(&rawPacket); // // // verify the packet is IPv4 // if (parsedPacket.isPacketOfType(pcpp::IPv4)) // { // // extract source and dest IPs // pcpp::IPv4Address srcIP = parsedPacket.getLayerOfType()->getSrcIPv4Address(); // pcpp::IPv4Address destIP = parsedPacket.getLayerOfType()->getDstIPv4Address(); // // // print source and dest IPs // std::cout << "Source IP is '" << srcIP << "'; " // << "Dest IP is '" << destIP << "'" << std::endl; // } // // // close the file // reader.close(); // } /** * A struct for collecting packet statistics */ // class PacketStats // { // public: // int ethPacketCount = 0; // int ipv4PacketCount = 0; // int ipv6PacketCount = 0; // int tcpPacketCount = 0; // int udpPacketCount = 0; // int dnsPacketCount = 0; // int httpPacketCount = 0; // int sslPacketCount = 0; // // // /** // * Clear all stats // */ // void clear() { ethPacketCount = ipv4PacketCount = ipv6PacketCount = tcpPacketCount = udpPacketCount = dnsPacketCount = httpPacketCount = sslPacketCount = 0; } // // // Constructor is optional here since the members are already initialized // PacketStats() = default; // // /** // * Collect stats from a packet // */ // void consumePacket(pcpp::Packet& packet) // { // if (packet.isPacketOfType(pcpp::Ethernet)) // ethPacketCount++; // if (packet.isPacketOfType(pcpp::IPv4)) // ipv4PacketCount++; // if (packet.isPacketOfType(pcpp::IPv6)) // ipv6PacketCount++; // if (packet.isPacketOfType(pcpp::TCP)) // tcpPacketCount++; // if (packet.isPacketOfType(pcpp::UDP)) // udpPacketCount++; // if (packet.isPacketOfType(pcpp::DNS)) // dnsPacketCount++; // if (packet.isPacketOfType(pcpp::HTTP)) // httpPacketCount++; // if (packet.isPacketOfType(pcpp::SSL)) // sslPacketCount++; // } // // /** // * Print stats to console // */ // void printToConsole() // { // std::cout // << "Ethernet packet count: " << ethPacketCount << std::endl // << "IPv4 packet count: " << ipv4PacketCount << std::endl // << "IPv6 packet count: " << ipv6PacketCount << std::endl // << "TCP packet count: " << tcpPacketCount << std::endl // << "UDP packet count: " << udpPacketCount << std::endl // << "DNS packet count: " << dnsPacketCount << std::endl // << "HTTP packet count: " << httpPacketCount << std::endl // << "SSL packet count: " << sslPacketCount << std::endl; // } // }; // // /** // * A callback function for the async capture which is called each time a packet is captured // */ // static void onPacketArrives(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* cookie) // { // // extract the stats object form the cookie // auto* stats = static_cast(cookie); // // // parsed the raw packet // pcpp::Packet parsedPacket(packet); // // // collect stats from packet // stats->consumePacket(parsedPacket); // } // // /** // * a callback function for the blocking mode capture which is called each time a packet is captured // */ // static bool onPacketArrivesBlockingMode(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* cookie) // { // // extract the stats object from the cookie // auto* stats = static_cast(cookie); // // // parsed the raw packet // pcpp::Packet parsedPacket(packet); // // // collect stats from packet // stats->consumePacket(parsedPacket); // // // return false means we don't want to stop capturing after this callback // return false; // } // // int sendPacketTest() // { // // IPv4 address of the interface we want to sniff // std::string interfaceIPAddr = "192.168.0.108"; // // // find the interface by IP address // pcpp::PcapLiveDevice* device = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIp(interfaceIPAddr); // // pcpp::PcapLiveDevice* device = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIp(interfaceIPAddr); // if (device == nullptr) { // std::cerr << "Cannot find interface with IPv4 address of '" << interfaceIPAddr << "'" << std::endl; // return 1; // } // // // before capturing packets let's print some info about this interface // std::cout // << "Interface info:" << std::endl // << " Interface name: " << device->getName() << std::endl // get interface name // << " Interface description: " << device->getDesc() << std::endl // get interface description // << " MAC address: " << device->getMacAddress() << std::endl // get interface MAC address // << " Default gateway: " << device ->getDefaultGateway() << std::endl // get default gateway // << " Interface MTU: " << device->getMtu() << std::endl; // get interface MTU // // // open the device before start capturing/sending packets // if (!device->open()) { // std::cerr << "Cannot open device" << std::endl; // return 1; // } // // // create the stats object // PacketStats stats; // // std::cout << std::endl << "Starting async capture..." << std::endl; // // // start capture in async mode. Give a callback function to call to whenever a packet is captured and the stats object as the cookie // device->startCapture(onPacketArrives, &stats); // // // sleep for 10 seconds in main thread, in the meantime packets are captured in the async thread // std::this_thread::sleep_for(std::chrono::seconds(10)); // // // stop capturing packets // device->stopCapture(); // // // print results // std::cout << "Results:" << std::endl; // stats.printToConsole(); // // // clear stats // stats.clear(); // // // Capturing packets in a packet vector // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // std::cout << std::endl << "Starting capture with packet vector..." << std::endl; // // // create an empty packet vector object // pcpp::RawPacketVector packetVec; // // // start capturing packets. All packets will be added to the packet vector // device->startCapture(packetVec); // // // sleep for 10 seconds in main thread, in the meantime packets are captured in the async thread // std::this_thread::sleep_for(std::chrono::seconds(10)); // // // stop capturing packets // device->stopCapture(); // // // go over the packet vector and feed all packets to the stats object // for (const auto& packet : packetVec) { // pcpp::Packet parsedPacket(packet); // stats.consumePacket(parsedPacket); // } // // // print results // std::cout << "Results:" << std::endl; // stats.printToConsole(); // // // clear stats // stats.clear(); // // // Capturing packets in blocking mode // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // std::cout << std::endl << "Starting capture in blocking mode..." << std::endl; // // // start capturing in blocking mode. Give a callback function to call to whenever a packet is captured, the stats // // object as the cookie and a 10 seconds timeout // device->startCaptureBlockingMode(onPacketArrivesBlockingMode, &stats, 10); // // // thread is blocked until capture is finished // // // capture is finished, print results // std::cout << "Results:" << std::endl; // stats.printToConsole(); // // stats.clear(); // // // Sending single packets // // ~~~~~~~~~~~~~~~~~~~~~~ // // std::cout << std::endl << "Sending " << packetVec.size() << " packets one by one..." << std::endl; // // // go over the vector of packets and send them one by one // bool allSent = std::all_of( // packetVec.begin(), // packetVec.end(), // [device](pcpp::RawPacket* packet) // { // return device->sendPacket(*packet); // } // ); // // if (!allSent) { // std::cerr << "Couldn't send packet" << std::endl; // return 1; // } // // std::cout << packetVec.size() << " packets sent" << std::endl; // // // Sending batch of packets // // ~~~~~~~~~~~~~~~~~~~~~~~~ // // std::cout << std::endl << "Sending " << packetVec.size() << " packets..." << std::endl; // // // send all packets in the vector. The returned number shows how many packets were actually sent (expected to be // // equal to vector size) // int packetsSent = device->sendPackets(packetVec); // // std::cout << packetsSent << " packets sent" << std::endl; // // // Using filters // // ~~~~~~~~~~~~~ // // // create a filter instance to capture only traffic on port 80 // pcpp::PortFilter portFilter(80, pcpp::SRC_OR_DST); // // // create a filter instance to capture only TCP traffic // pcpp::ProtoFilter protocolFilter(pcpp::TCP); // // // create an AND filter to combine both filters - capture only TCP traffic on port 80 // pcpp::AndFilter andFilter; // andFilter.addFilter(&portFilter); // andFilter.addFilter(&protocolFilter); // // // set the filter on the device // device->setFilter(andFilter); // // std::cout << std::endl << "Starting packet capture with a filter in place..." << std::endl; // // // start capture in async mode. Give a callback function to call to whenever a packet is captured and the stats // // object as the cookie // device->startCapture(onPacketArrives, &stats); // // // sleep for 10 seconds in main thread, in the meantime packets are captured in the async thread // std::this_thread::sleep_for(std::chrono::seconds(10)); // // // stop capturing packets // device->stopCapture(); // // // print results - should capture only packets which match the filter (which is TCP port 80) // std::cout << "Results:" << std::endl; // stats.printToConsole(); // // return 0; // } // std::string getProtocolTypeAsString(pcpp::ProtocolType protocolType) { switch (protocolType) { case pcpp::Ethernet: return "Ethernet"; case pcpp::IPv4: return "IPv4"; case pcpp::TCP: return "TCP"; case pcpp::HTTPRequest: case pcpp::HTTPResponse: return "HTTP"; default: return "Unknown"; } } std::string printTcpFlags(pcpp::TcpLayer* tcpLayer) { std::string result; auto* tcpHeader = tcpLayer->getTcpHeader(); if (tcpHeader->synFlag) result += "SYN "; if (tcpHeader->ackFlag) result += "ACK "; if (tcpHeader->pshFlag) result += "PSH "; if (tcpHeader->cwrFlag) result += "CWR "; if (tcpHeader->urgFlag) result += "URG "; if (tcpHeader->eceFlag) result += "ECE "; if (tcpHeader->rstFlag) result += "RST "; if (tcpHeader->finFlag) result += "FIN "; return result; } std::string printTcpOptionType(pcpp::TcpOptionEnumType optionType) { switch (optionType) { case pcpp::TcpOptionEnumType::Nop: return "NOP"; case pcpp::TcpOptionEnumType::Timestamp: return "Timestamp"; default: return "Other"; } } std::string printHttpMethod(pcpp::HttpRequestLayer::HttpMethod httpMethod) { switch (httpMethod) { case pcpp::HttpRequestLayer::HttpGET: return "GET"; case pcpp::HttpRequestLayer::HttpPOST: return "POST"; default: return "Other"; } } // int testParsePacket() // { // // use the IFileReaderDevice interface to automatically identify file type (pcap/pcap-ng) // // and create an interface instance that both readers implement // std::unique_ptr reader(pcpp::IFileReaderDevice::getReader("1_http_packet.pcap")); // // // verify that a reader interface was indeed created // if (reader == nullptr) { // std::cerr << "Cannot determine reader for file type" << std::endl; // return 1; // } // // // open the reader for reading // if (!reader->open()) { // std::cerr << "Cannot open input.pcap for reading" << std::endl; // return 1; // } // // // read the first (and only) packet from the file // pcpp::RawPacket rawPacket; // if (!reader->getNextPacket(rawPacket)) { // std::cerr << "Couldn't read the first packet in the file" << std::endl; // return 1; // } // // // close the file reader, we don't need it anymore // reader->close(); // // // parse the raw packet into a parsed packet // pcpp::Packet parsedPacket(&rawPacket); // // // first let's go over the layers one by one and find out its type, its total length, its header length and its // // payload length // for (pcpp::Layer* curLayer = parsedPacket.getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer()) { // std::cout << "Layer type: " << getProtocolTypeAsString(curLayer->getProtocol()) << "; " // get layer type // << "Total data: " << curLayer->getDataLen() << " [bytes]; " // get total length of the layer // << "Layer data: " << curLayer->getHeaderLen() << " [bytes]; " // get the header length of the layer // << "Layer payload: " << curLayer->getLayerPayloadSize() << " [bytes]" // get the payload length of // // the layer (equals total // // length minus header length) // << std::endl; // } // // // now let's get the Ethernet layer // pcpp::EthLayer* ethernetLayer = parsedPacket.getLayerOfType(); // if (ethernetLayer == nullptr) { // std::cerr << "Something went wrong, couldn't find Ethernet layer" << std::endl; // return 1; // } // // // print the source and dest MAC addresses and the Ether type // std::cout << std::endl // << "Source MAC address: " << ethernetLayer->getSourceMac() << std::endl // << "Destination MAC address: " << ethernetLayer->getDestMac() << std::endl // << "Ether type = 0x" << std::hex << pcpp::netToHost16(ethernetLayer->getEthHeader()->etherType) // << std::endl; // // // // let's get the IPv4 layer // pcpp::IPv4Layer* ipLayer = parsedPacket.getLayerOfType(); // if (ipLayer == nullptr) { // std::cerr << "Something went wrong, couldn't find IPv4 layer" << std::endl; // return 1; // } // // // print source and dest IP addresses, IP ID and TTL // std::cout << std::endl // << "Source IP address: " << ipLayer->getSrcIPAddress() << std::endl // << "Destination IP address: " << ipLayer->getDstIPAddress() << std::endl // << "IP ID: 0x" << std::hex << pcpp::netToHost16(ipLayer->getIPv4Header()->ipId) << std::endl // << "TTL: " << std::dec << (int)ipLayer->getIPv4Header()->timeToLive << std::endl; // // // // let's get the TCP layer // auto* tcpLayer = parsedPacket.getLayerOfType(); // if (tcpLayer == nullptr) // { // std::cerr << "Something went wrong, couldn't find TCP layer" << std::endl; // return 1; // } // // // print TCP source and dest ports, window size, and the TCP flags that are set in this layer // std::cout << std::endl // << "Source TCP port: " << tcpLayer->getSrcPort() << std::endl // << "Destination TCP port: " << tcpLayer->getDstPort() << std::endl // << "Window size: " << pcpp::netToHost16(tcpLayer->getTcpHeader()->windowSize) << std::endl // << "TCP flags: " << printTcpFlags(tcpLayer) << std::endl; // // std::cout << "TCP options: "; // for (pcpp::TcpOption tcpOption = tcpLayer->getFirstTcpOption(); tcpOption.isNotNull(); // tcpOption = tcpLayer->getNextTcpOption(tcpOption)) // { // std::cout << printTcpOptionType(tcpOption.getTcpOptionEnumType()) << " "; // } // std::cout << std::endl; // // // let's get the HTTP request layer // auto* httpRequestLayer = parsedPacket.getLayerOfType(); // if (httpRequestLayer == nullptr) // { // std::cerr << "Something went wrong, couldn't find HTTP request layer" << std::endl; // return 1; // } // // // print HTTP method and URI. Both appear in the first line of the HTTP request // std::cout << std::endl // << "HTTP method: " << printHttpMethod(httpRequestLayer->getFirstLine()->getMethod()) << std::endl // << "HTTP URI: " << httpRequestLayer->getFirstLine()->getUri() << std::endl; // // // print values of the following HTTP field: Host, User-Agent and Cookie // std::cout << "HTTP host: " << httpRequestLayer->getFieldByName(PCPP_HTTP_HOST_FIELD)->getFieldValue() << std::endl // << "HTTP user-agent: " << httpRequestLayer->getFieldByName(PCPP_HTTP_USER_AGENT_FIELD)->getFieldValue() // << std::endl // << "HTTP cookie: " << httpRequestLayer->getFieldByName(PCPP_HTTP_COOKIE_FIELD)->getFieldValue() // << std::endl; // // // print the full URL of this request // std::cout << "HTTP full URL: " << httpRequestLayer->getUrl() << std::endl; // } class CoRet { public: class promise_type { public: CoRet get_return_object() { return CoRet(std::coroutine_handle::from_promise(*this)); } std::suspend_never initial_suspend() { return {}; } // 协程启动时调用 std::suspend_never final_suspend() noexcept { return {}; } // 协程结束时调用 std::suspend_always yield_value() { return {}; } // 协程函数中有co_yield时调用 void unhandled_exception() {} // 协程函数发生异常时调用 // void return_void() {} // 协程函数 void return_value(int v) { m_value = v; } // 协程函数中有co_return 有值时调用 public: int get() { return m_value; } private: int m_value; }; CoRet(std::coroutine_handle coroutine) : m_handle(coroutine) {} // void resume() { m_handle.resume(); } int get() { m_handle.resume(); return m_handle.promise().get(); } private: // 协程本身 std::coroutine_handle m_handle; }; class Input { public: bool await_ready() { return false; } // false表示未准备好,需要暂停 void await_suspend(std::coroutine_handle<> handle) {} // 在协程暂停后,执行的方法 void await_resume() {} // 协程调用resume后,回调此方法,co_await 的返回值 }; /** * 协程函数 * 特征:返回值的类型 * @return */ CoRet Guess() { Input input; co_await input; // co_await 一个对象时,该对象需要实现系列特定方法 std::cout << "Hello Coroutine" << std::endl; // co_return 666; } int main(int argc, char* argv[]) { // CoRet ret = Guess(); std::cout << "Hello Coroutine" << std::endl; // std::this_thread::sleep_for(std::chrono::seconds(3)); // std::chrono::time_point clock = std::chrono::steady_clock::now() + std::chrono::seconds(1); // std::this_thread::sleep_until(clock); // std::thread t1([&] { // std::cout << "Hello thread" << std::endl; // }); // int value = ret.get(); // std::jthread t2([&] { // std::cout << "Hello Thread" << std::endl; // }); // std::future ft = std::async([&] -> int { // std::cout << "Hello Thread" << std::endl; // return 2; // }); // // int ret = ft.get(); // std::promise pret; // std::thread t1([&] { // std::cout << "Hello thread" << std::endl; // pret.set_value(10); // }); // std::future fret = pret.get_future(); // int ret = fret.get(); std::vector arr; std::mutex mtx; std::thread t1([&]() { for (int i = 0; i < 1000; i++) { mtx.lock(); arr.push_back(i); // 将对某块内存的访问,标记在一个板上 mtx.unlock(); } }); std::thread t2([&]() { for (int i = 0; i < 1000; i++) { mtx.lock(); arr.push_back(i); mtx.unlock(); } }); t1.join(); t2.join(); std::cout << "main: make a guess ..." << std::endl; // t1.join(); // std::this_thread::sleep_for(std::chrono::seconds(3)); return 0; } // 通过arp协议,通过ip地址换取Mac地址 pcpp::AppName::init(argc, argv); // 数据库 duckdb_database db; // 数据库连接 duckdb_connection conn; // 查询结果 duckdb_result result; // 连接数据库文件 USE XXX if (duckdb_open(nullptr, &db) == DuckDBError) { std::cout << "DuckDB Open Error" << std::endl; duckdb_destroy_result(&result); duckdb_disconnect(&conn); duckdb_close(&db); return -1; } // 连接数据库 conn if (duckdb_connect(db, &conn) == DuckDBError) { std::cout << "DuckDB Connect Error" << std::endl; duckdb_destroy_result(&result); duckdb_disconnect(&conn); duckdb_close(&db); return -1; } // 执行SQL,创建表 if (duckdb_query(conn, "CREATE TABLE integers(i INTEGER, j INTEGER);", NULL) == DuckDBError) { fprintf(stderr, "Failed to query database\n"); duckdb_destroy_result(&result); duckdb_disconnect(&conn); duckdb_close(&db); return -1; } // 执行SQL,向表里插入数据 if (duckdb_query(conn, "INSERT INTO integers VALUES (3, 4), (5, 6), (7, NULL);", NULL) == DuckDBError) { fprintf(stderr, "Failed to query database\n"); duckdb_destroy_result(&result); duckdb_disconnect(&conn); duckdb_close(&db); } // 执行SQL,从表里查询数据 if (duckdb_query(conn, "SELECT * FROM integers", &result) == DuckDBError) { fprintf(stderr, "Failed to query database\n"); duckdb_destroy_result(&result); duckdb_disconnect(&conn); duckdb_close(&db); } // print the names of the result idx_t row_count = duckdb_row_count(&result); idx_t column_count = duckdb_column_count(&result); for (size_t i = 0; i < column_count; i++) { printf("%s ", duckdb_column_name(&result, i)); } printf("\n"); // print the data of the result for (size_t row_idx = 0; row_idx < row_count; row_idx++) { for (size_t col_idx = 0; col_idx < column_count; col_idx++) { char *val = duckdb_value_varchar(&result, col_idx, row_idx); printf("%s ", val); duckdb_free(val); } printf("\n"); } duckdb_destroy_result(&result); duckdb_disconnect(&conn); duckdb_close(&db); // 会在内核创建两个队列(sq和cq),然后在liburing中,映射出两个结构体,用结构体来管理内核中的队列 io_uring ring; // 会在内核创建两个队列(sq和cq),然后在liburing中,映射出两个结构体,用结构体来管理内核中的队列 io_uring_queue_init(10, &ring, 0); // 从ring中获取一个sq的管理对象 // io_uring_seq* seq = io_uring_sqe* sqe = io_uring_get_sqe(&ring); // 从文件中读取内容后,要存入的缓存 char buf[6]; // 向sq队列准备一个从键盘读取数据的事件 io_uring_prep_read(sqe, STDIN_FILENO, buf, sizeof(buf), 0); io_uring_sqe_set_data64(sqe, 42); // 将ring里准备的事件统一提交给内核的sq,让内核处理 io_uring_submit(&ring); // 提交队列,记录了内核处理事件的结果 io_uring_cqe* cqe; // 从内核ring中,等待sq的事件处理完,然后获取一个cqe io_uring_wait_cqe(&ring, &cqe); // 此处会等待 // 从cq中查看有多少个事件 io_uring_cqe* cqes[10]; // 尝试从cq中取10个处理完的事件,返回实际获取到的事件个数 int count = io_uring_peek_batch_cqe(&ring, cqes, 10); printf("count: %d\n", count); std::cout << cqe->res << std::endl; // 事件处理完,产生的数据 std::cout << cqe->user_data << std::endl; io_uring_cqe_seen(&ring, cqe); std::cout << buf << std::endl; // 销毁liburing中的环路队列 io_uring_queue_exit(&ring); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class PacketStats { public: int ethPacketCount = 0; int ipv4PacketCount = 0; int ipv6PacketCount = 0; int tcpPacketCount = 0; int udpPacketCount = 0; int dnsPacketCount = 0; int httpPacketCount = 0; int sslPacketCount = 0; /** * Clear all stats */ void clear() { ethPacketCount = ipv4PacketCount = ipv6PacketCount = tcpPacketCount = udpPacketCount = dnsPacketCount = httpPacketCount = sslPacketCount = 0; } // Constructor is optional here since the members are already initialized PacketStats() = default; /** * Collect stats from a packet */ void consumePacket(pcpp::Packet& packet) { if (packet.isPacketOfType(pcpp::Ethernet)) ethPacketCount++; if (packet.isPacketOfType(pcpp::IPv4)) ipv4PacketCount++; if (packet.isPacketOfType(pcpp::IPv6)) ipv6PacketCount++; if (packet.isPacketOfType(pcpp::TCP)) tcpPacketCount++; if (packet.isPacketOfType(pcpp::UDP)) udpPacketCount++; if (packet.isPacketOfType(pcpp::DNS)) dnsPacketCount++; if (packet.isPacketOfType(pcpp::HTTP)) httpPacketCount++; if (packet.isPacketOfType(pcpp::SSL)) sslPacketCount++; } /** * Print stats to console */ void printToConsole() { std::cout << "Ethernet packet count: " << ethPacketCount << std::endl << "IPv4 packet count: " << ipv4PacketCount << std::endl << "IPv6 packet count: " << ipv6PacketCount << std::endl << "TCP packet count: " << tcpPacketCount << std::endl << "UDP packet count: " << udpPacketCount << std::endl << "DNS packet count: " << dnsPacketCount << std::endl << "HTTP packet count: " << httpPacketCount << std::endl << "SSL packet count: " << sslPacketCount << std::endl; } }; std::string getProtocolTypeAsString(pcpp::ProtocolType protocolType) { switch (protocolType) { case pcpp::Ethernet: return "Ethernet"; case pcpp::IPv4: return "IPv4"; case pcpp::TCP: return "TCP"; case pcpp::HTTPRequest: case pcpp::HTTPResponse: return "HTTP"; default: return "Unknown"; } } /** * 抓到一个数据包时调用 * @param packet 抓到的数据包 * @param device 数据包来自的网口对象 * @param cookie 从开启抓包线程传来的数据 */ static void onPacketArrives(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* device, void* cookie) { std::cout << "抓到一个数据包.." << std::endl; // 通过RawPacket构建parsedPacket,捕获的包是rawpacket包 pcpp::Packet parsedPacket(packet); // payload length for (pcpp::Layer* curLayer = parsedPacket.getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer()) { std::cout << "Layer type: " << getProtocolTypeAsString(curLayer->getProtocol()) << "; " // get layer type << "Total data: " << curLayer->getDataLen() << " [bytes]; " // get total length of the layer << "Layer data: " << curLayer->getHeaderLen() << " [bytes]; " // get the header length of the layer << "Layer payload: " << curLayer->getLayerPayloadSize() << " [bytes]" // get the payload length of // the layer (equals total // length minus header length) << std::endl; } } int main(int argc, char * argv[]) { // domain: 套接字使用的协议族 // type: 套接字类型传输类型 int socketFd = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in servAddr; servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听端口 (2字节,0~65535范围) servAddr.sin_port = htons(9999); // 将监听的本地IP和端口与文件描述符绑定 bind(socketFd, (sockaddr *)&servAddr, sizeof(servAddr)); // 开启监听 listen(socketFd, 10); // 定义客户端 sockaddr_in clientAddr; socklen_t clientAddrLen = sizeof(clientAddr); // 不断从对应的socket文件中获取客户端的连接 while (true) { // 依次递增 int clientFd = accept(socketFd, (sockaddr *)&clientAddr, &clientAddrLen); printf("Client fd: %d\n", clientFd); } getchar(); // // 与网口绑定的ip // std::string interfaceIPAddr = "192.168.0.108"; // // // 根据ip地址,找到绑定的网口对象 // pcpp::PcapLiveDevice* device = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIp(interfaceIPAddr); // // // 打开本机网口 // if (!device->open()) { // std::cerr << "Cannot open device" << std::endl; // return 1; // } // // // 源Ip地址 // pcpp::IPv4Address srcIpv4Address("192.168.0.108"); // // 源Mac地址 // pcpp::MacAddress srcMacAddress("e0:e1:a9:38:41:41"); // // // 目标Ip地址 // pcpp::IPv4Address dstIpv4Address("192.168.0.102"); // // // 多少秒回复 // double arpResponseTimeMS = 0; // // 超时秒数(5秒) // int timeoutSec = pcpp::NetworkUtils::DefaultTimeout; // // // 尝试3次 // for (size_t i = 0; i < 3; i ++) { // // use the getMacAddress utility to send an ARP request and resolve the MAC address // // 返回目标设备的mac地址 // pcpp::MacAddress result = pcpp::NetworkUtils::getInstance().getMacAddress(dstIpv4Address, device, arpResponseTimeMS, // srcMacAddress, srcIpv4Address, timeoutSec); // // // failed fetching MAC address // if (result == pcpp::MacAddress::Zero) { // // PcapPlusPlus logger saves the last internal error message // std::cout << "Arping index=" << i << " : " << pcpp::Logger::getInstance().getLastError() << std::endl; // } // else // Succeeded fetching MAC address // { // // output ARP ping data // std::cout.precision(3); // std::cout << "Reply from " << dstIpv4Address << " " // << "[" << result << "] " << std::fixed << arpResponseTimeMS << "ms " // << "index=" << i << std::endl; // } // } // 发包计划生成模块 // std::jthread makeSendPacketsPlanThread([]() { // // }); // 发包模块 // std::jthread sendPacketsThread([]() { // // 与网口绑定的ip // std::string interfaceIPAddr = "192.168.0.108"; // // // 根据ip地址,找到绑定的网口对象 // pcpp::PcapLiveDevice* device = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIp(interfaceIPAddr); // // // 打开本机网口 // if (!device->open()) { // std::cerr << "Cannot open device" << std::endl; // return 1; // } // // while (true) { // std::cout << "发送多个数据包..." << std::endl; // // // 批量发送 // pcpp::RawPacketVector rawPacketsVector; // for (size_t i = 0; i < 3; i ++) { // // 构建数据包 // pcpp::Packet* packet = new pcpp::Packet; // // // eth层 // pcpp::EthLayer ethLayer(pcpp::MacAddress("e0:e1:a9:38:41:41"), pcpp::MacAddress("2c:56:dc:3a:99:0f")); // packet->addLayer(ðLayer); // // 网络层 // pcpp::IPv4Layer ipv4Layer(pcpp::IPv4Address("192.168.0.108"), pcpp::IPv4Address("192.168.0.102")); // // ipv4Layer.getIPv4Header()->ipId = pcpp::hostToNet16(2000); // // ipv4Layer.getIPv4Header()->timeToLive = 64; // packet->addLayer(&ipv4Layer); // // 传输层 // pcpp::TcpLayer tcpLayer(65002, 80); // packet->addLayer(&tcpLayer); // // 应用层 // // pcpp::HttpRequestLayer requestLayer(pcpp::HttpRequestLayer::HttpGET, "http://192.168.0.102/v1/getSysConfig", pcpp::HttpVersion::OneDotZero); // // packet->addLayer(&requestLayer); // // // 根据不同层的协议,计算data // packet->computeCalculateFields(); // // // 将构建好的数据包集中 // rawPacketsVector.pushBack(packet->getRawPacket()); // } // // // // // payload length // // for (pcpp::Layer* curLayer = packet.getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer()) { // // std::cout << "Layer type: " << getProtocolTypeAsString(curLayer->getProtocol()) << "; " // get layer type // // << "Total data: " << curLayer->getDataLen() << " [bytes]; " // get total length of the layer // // << "Layer data: " << curLayer->getHeaderLen() << " [bytes]; " // get the header length of the layer // // << "Layer payload: " << curLayer->getLayerPayloadSize() << " [bytes]" // get the payload length of // // // the layer (equals total // // // length minus header length) // // << std::endl; // // } // // // 发送数据包 // device->sendPackets(rawPacketsVector); // // // 清空数据包 // rawPacketsVector.clear(); // // // 清空 // std::this_thread::sleep_for(std::chrono::seconds(5)); // } // }); // 抓包模块 // std::jthread capturePacketsThread([]() { // // 与网口绑定的ip // std::string interfaceIPAddr = "192.168.0.108"; // // // 根据ip地址,找到绑定的网口对象 // pcpp::PcapLiveDevice* device = pcpp::PcapLiveDeviceList::getInstance().getDeviceByIp(interfaceIPAddr); // // // 打开本机网口 // if (!device->open()) { // std::cerr << "Cannot open device" << std::endl; // return 1; // } // // // 设定包过滤器 // // 综合先过滤条件 // pcpp::AndFilter andFilter; // // 限定源ip地址 // pcpp::IPFilter ipFilter("192.168.0.108", pcpp::Direction::SRC); // andFilter.addFilter(&ipFilter); // // 限定协议 tcp // pcpp::ProtoFilter protoFilter(pcpp::TCP); // andFilter.addFilter(&protoFilter); // // 限定端口 到我的65001端口 // pcpp::PortFilter portFilter(65001, pcpp::Direction::DST); // andFilter.addFilter(&portFilter); // // // 将过滤条件绑定给网口 // device->setFilter(andFilter); // // // 开启抓包线程 // PacketStats packetStats; // device->startCapture(onPacketArrives, &packetStats); // // while (true) { // // std::cout << "makeSendPacketsPlanThread..." << std::endl; // // std::this_thread::sleep_for(std::chrono::seconds(1)); // } // }); // 锁定主线程 // while (true) {} return 0; } #include #include #include #include #include #include #include #include #include #include #define PACKET_SIZE 4096 unsigned short checksum(unsigned short* b, int len) { unsigned short* buf = b; unsigned int sum = 0; unsigned short result; for (sum = 0; len > 1; len -= 2) sum += *buf++; if (len == 1) sum += *(unsigned char*)buf; sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); result = ~sum; return result; } void ping(sockaddr_in *addr) { const int val = 255; int i, sockfd; icmp sendicmp; sockaddr_in from; char recvbuf[PACKET_SIZE] = {0}; sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sockfd < 0) { printf("socket() failed\n"); return; } setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)); sendicmp.icmp_type = ICMP_ECHO; sendicmp.icmp_code = 0; sendicmp.icmp_cksum = 0; // sendicmp.icmp = getpid(); // sendicmp.icmp_hun.ih_idseq.icd_seq = 1; sendicmp.icmp_cksum = checksum((unsigned short *)&sendicmp, sizeof(sendicmp)); if (sendto(sockfd, &sendicmp, sizeof(sendicmp), 0, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) < 0) { printf("sendto() failed\n"); return; } sockaddr_in from_addr; socklen_t from_len = sizeof(from_addr); for (size_t j = 0; j < 5; j++) { std::cout << "Hello" << std::endl; if (recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&from_addr, &from_len) < 0) { printf("recvfrom() failed\n"); return; } std::cout << recvbuf << std::endl; } // if (recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&from_addr, &from_len) < 0) { // printf("recvfrom() failed\n"); // return; // } ip *iph = (struct ip *)recvbuf; icmp *icmph = (struct icmp *)(recvbuf + (iph->ip_hl<<2)); if (icmph->icmp_type == ICMP_ECHOREPLY) { printf("Received ICMP echo reply from %s\n", inet_ntoa(from.sin_addr)); } else { printf("Received non-echo reply packet\n"); } } int main() { sockaddr_in addr_ping, *addr; addr = &addr_ping; memset(addr, 0, sizeof(sockaddr_in)); addr->sin_family = AF_INET; addr->sin_addr.s_addr = inet_addr("192.168.0.100"); // Google DNS server ping(addr); return 0; } pcpp::IPv4Address ipv4Address("192.168.0.108"); pcpp::RawSocketDevice device(ipv4Address); if (!device.open()) { std::cerr << "设备无法打开.." << std::endl; return; } pcpp::RawPacket rawPacket; pcpp::RawSocketDevice::RecvPacketResult result = device.receivePacket(rawPacket, true, -1); if (result == pcpp::RawSocketDevice::RecvError) { std::cerr << "数据包获取失败.." << std::endl; return; } if (result == pcpp::RawSocketDevice::RecvTimeout) { std::cerr << "数据包获取超时.." << std::endl; } std::cout << "数据包获取成功.." << result << std::endl; // 将数据包中的二进制数据解析为对应的网络协议数据 pcpp::Packet parsedPacket(&rawPacket); std::cout << parsedPacket << std::endl; // verify the packet is IPv4 if (parsedPacket.isPacketOfType(pcpp::IPv4)) { // extract source and dest IPs pcpp::IPv4Address srcIP = parsedPacket.getLayerOfType()->getSrcIPv4Address(); pcpp::IPv4Address destIP = parsedPacket.getLayerOfType()->getDstIPv4Address(); // print source and dest IPs std::cout << "Source IP is '" << srcIP << "'; " << "Dest IP is '" << destIP << "'" << std::endl; } device.close(); std::jthread athread([] { }); std::jthread bThread([] { std::this_thread::sleep_for(std::chrono::seconds(3)); pcpp::IPv4Address ipv4Address("192.168.0.108"); pcpp::RawSocketDevice device(ipv4Address); if (!device.open()) { std::cerr << "设备无法打开.." << std::endl; return; } pcpp::Packet packet(1); pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("192.168.0.108"), pcpp::IPv4Address("192.168.0.100")); packet.addLayer(&ipLayer); packet.computeCalculateFields(); if (!device.sendPacket(packet.getRawPacket())) { std::cerr << "数据包发送失败.." << std::endl; return; } std::cout << "数据包发送成功.." << std::endl; device.close(); }); class Server { public: Server(boost::asio::io_context& io_context, unsigned short port) : m_acceptor(io_context, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) { } private: void doAccept() { m_acceptor.async_accept([this](boost::system::error_code errorCode, boost::asio::ip::tcp::socket socket) { if (!errorCode) { } }); } private: boost::asio::ip::tcp::acceptor m_acceptor; }; std::cout << asio2::ping::execute("192.168.0.100").milliseconds() << std::endl; // std::cout << "Hello" << std::endl; // execute with error, print the error message. // if (asio2::get_last_error()) // std::cout << asio2::last_error_msg() << std::endl; asio2::ping ping; ping.set_timeout(std::chrono::seconds(4)); ping.set_interval(std::chrono::seconds(1)); ping.bind_init([&]() { asio::ip::address_v4 interfaceAddress = asio::ip::address_v4::from_string("192.168.0.108"); ping.socket().set_option(asio::ip::multicast::outbound_interface(interfaceAddress)); }); ping.bind_recv([](asio2::icmp_rep& rep) { if (rep.is_timeout()) std::cout << "request timed out" << std::endl; else std::cout << rep.total_length() - rep.header_length() << " bytes from " << rep.source_address() << " to " << rep.destination_address() << ": icmp_seq=" << rep.sequence_number() << ", ttl=" << rep.time_to_live() << ", time=" << rep.milliseconds() << "ms" << std::endl; }); ping.bind_start([](){ if (asio2::get_last_error()) std::cout << asio2::last_error_msg() << std::endl; }); ping.start("192.168.0.100"); while (std::getchar() != '\n'); ping.stop(); printf("loss rate : %.0lf%% average time : %ldms\n", ping.plp(), long(std::chrono::duration_cast(ping.avg_lag()).count())); while (std::getchar() != '\n'); std::ifstream serial_file("/var/lib/dbus/machine-id", std::ifstream::in); if (serial_file.is_open()) { std::string product_serial; std::getline(serial_file, product_serial); serial_file.close(); // Remove any trailing newline characters if (!product_serial.empty() && product_serial.back() == '\n') { product_serial.pop_back(); } std::cout << "Product Serial: " << product_serial << std::endl; } else { std::cerr << "Error: Could not open /sys/class/dmi/id/product_serial. " << "This file typically requires root privileges to read." << std::endl; return 1; } void ProberServer::callEnableProber() { // 1、根据监听目标配置,创建连接通道对象 std::shared_ptr channel = grpc::CreateChannel("192.168.0.108:65001", grpc::InsecureChannelCredentials()); // 2、创建远程调用代理 std::unique_ptr stub = NetworkProberServer::NewStub(channel); // 3 创建请求和响应对象 // 3.1 context grpc::ClientContext clientContext; // 3.2 request // Request request; // request.set_name("hello"); // 3.3 response EnableProberResponse response; // 4 send a service call grpc::Status status = stub->enableProber(&clientContext, google::protobuf::Empty(), &response); // 5 handle response // 5.1 handle error resp if (!status.ok()) { std::cerr << status.error_code() << ": " << status.error_message() << std::endl; return; } } void ProberServer::callRegisterProbe() { // 1、根据监听目标配置,创建连接通道对象 std::shared_ptr channel = grpc::CreateChannel("192.168.0.101:65003", grpc::InsecureChannelCredentials()); // 2、创建远程调用代理 std::unique_ptr stub = network_perception::NetworkPerceptionServer::NewStub(channel); // 3 创建请求和响应对象 // 3.1 context grpc::ClientContext clientContext; // 3.2 request network_perception::RegisterProbeRequest request; request.set_version("软件版本"); request.set_machine_id("唯一标识"); request.set_public_model("公开型号"); request.set_secret_key("注册成功后有该值,首次启动留空"); // 3.3 response network_perception::RegisterProbeResponse response; // 4 send a service call (阻塞,直到返回结果) grpc::Status status = stub->registerProbe(&clientContext, request, &response); // 5 handle response // 5.1 handle error resp if (!status.ok()) { std::cerr << status.error_code() << ": " << status.error_message() << std::endl; return; } } auto startTime = std::chrono::system_clock::now(); // 开始发送 ping 给 host (经测试,平均发送1个请求耗时为3ms以内) ping.start("www.baidu.com"); auto diff = std::chrono::duration_cast(std::chrono::system_clock::now() - startTime).count(); class ProberService final : public NetworkProberServer::Service { public: /** * 接口 - 启用探针 * @param context 上下文对象,描述了这次远程请求的基础信息(适用:权限验证等) * @param request 请求参数,用于从客户端接收请求数据 * @param response 响应参数,用于向客户端发送响应数据 * @return 函数的执行状态 */ grpc::Status enableProber(grpc::ServerContext *context, const google::protobuf::Empty *request, EnableProberResponse *response) override { std::cout << "call enableProber..." << std::endl; response->set_code(20000); response->set_msg("success"); return grpc::Status::OK; } /** * 接口 - 停用探针 * @param context 上下文对象,描述了这次远程请求的基础信息(适用:权限验证等) * @param request 请求参数,用于从客户端接收请求数据 * @param response 响应参数,用于向客户端发送响应数据 * @return 函数的执行状态 */ grpc::Status disableProber(grpc::ServerContext *context, const google::protobuf::Empty *request, DisableProberResponse *response) override { std::cout << "call disableProber..." << std::endl; response->set_code(20000); response->set_msg("success"); return grpc::Status::OK; } ~NetworkProberService() override { } }; // // // 3 创建请求和响应对象 // // 3.1 context // grpc::ClientContext clientContext; // // grpc::CompletionQueue cq; // // example::DataRequest request; // request.set_message("Hello World"); // // stub->async() // 创建 readerwriter,读取写入都是它 // std::unique_ptr> rpc(stub->AsyncStreamData(&clientContext, &cq)); // 子线程发送请求 // std::thread writer([rpc]() { // // 发送请求 // rpc->Write(example::DataRequest()); // // 发送结束 // rpc->WritesDone(); // }); // 主线程读取响应 // 读取响应 // while (stream->Read(&server_note)) { // } // writer.join(); // // 等待返回状态 // Status status = stream->Finish(); // ... printf("Found: %s CPU\n", data.vendor_str); // print out the vendor string (e.g. `GenuineIntel') printf("Processor model is `%s'\n", data.cpu_codename); // print out the CPU code name (e.g. `Pentium 4 (Northwood)') printf("The full brand string is `%s'\n", data.brand_str); // print out the CPU brand string printf("The processor has %dK L1 cache and %dK L2 cache\n", data.l1_data_cache, data.l2_cache); // print out cache size information printf("The processor has %d cores and %d logical processors\n", data.num_cores, data.num_logical_cpus); printf("Supported multimedia instruction sets:\n"); printf(" MMX : %s\n", data.flags[CPU_FEATURE_MMX] ? "present" : "absent"); printf(" MMX-extended: %s\n", data.flags[CPU_FEATURE_MMXEXT] ? "present" : "absent"); printf(" SSE : %s\n", data.flags[CPU_FEATURE_SSE] ? "present" : "absent"); printf(" SSE2 : %s\n", data.flags[CPU_FEATURE_SSE2] ? "present" : "absent"); printf(" 3DNow! : %s\n", data.flags[CPU_FEATURE_3DNOW] ? "present" : "absent"); printf("CPU clock is: %d MHz (according to your OS)\n", cpu_clock_by_os()); // print out the CPU clock, according to the OS printf("CPU clock is: %d MHz (tested)\n", cpu_clock_measure(200, 0)); Found: GenuineIntel CPU Processor model is `Core i5 (Haswell)' The full brand string is `Intel(R) Core(TM) i5-4440 CPU @ 3.10GHz' The processor has 32K L1 cache and 256K L2 cache The processor has 4 cores and 4 logical processors Supported multimedia instruction sets: MMX : present MMX-extended: absent SSE : present SSE2 : present 3DNow! : absent CPU clock is: 3092 MHz (according to your OS) CPU clock is: 3092 MHz (tested) // // Created by twetec on 25-6-20. // #include #include #include "prober_service.h" namespace network_prober::rpc { ProberServer &ProberServer::getInstance() { static ProberServer instance; return instance; } void ProberServer::start(const std::string &listenIP, size_t listenPort) { // 1、构建服务器配置对象 grpc::ServerBuilder serverBuilder; // 2、配置服务器 - 监听地址和端口 serverBuilder.AddListeningPort(listenIP + ":" + std::to_string(listenPort), grpc::InsecureServerCredentials()); // 3、创建探针服务 ProberService proberService; // 4、将服务注册给服务器 serverBuilder.RegisterService(&proberService); // 5、启动服务器 std::unique_ptr serverPtr = serverBuilder.BuildAndStart(); // 6、转换服务器资源的拥有全 m_proberServerPtr = std::move(serverPtr); SPDLOG_INFO("探针 rpc server 启动成功.."); // 7、让服务器等待处理(程序在此阻塞) m_proberServerPtr->Wait(); } ProberServer::ProberServer() { } ProberServer::~ProberServer() { } } // // Created by twetec on 25-6-22. // #include "prober_service.h" namespace network_prober ::rpc { grpc::Status ProberService::enableProber(grpc::ServerContext *context, const google::protobuf::Empty *request, EnableProberResponse *response) { std::cout << "call enableProber..." << std::endl; response->set_code(20000); response->set_msg("success"); return grpc::Status::OK; } grpc::Status ProberService::disableProber(grpc::ServerContext *context, const google::protobuf::Empty *request, DisableProberResponse *response) { std::cout << "call disableProber..." << std::endl; response->set_code(20000); response->set_msg("success"); return grpc::Status::OK; } ProberService::~ProberService() { } } // // Created by twetec on 25-6-22. // #ifndef NETWORK_PROBER_RPC_PROBER_SERVICE_H #define NETWORK_PROBER_RPC_PROBER_SERVICE_H namespace network_prober ::rpc { /** * 定义探针服务类 */ class ProberService final : public NetworkProberServer::Service { public: /** * 接口 - 启用探针 * @param context 上下文对象,描述了这次远程请求的基础信息(适用:权限验证等) * @param request 请求参数,用于从客户端接收请求数据 * @param response 响应参数,用于向客户端发送响应数据 * @return 函数的执行状态 */ grpc::Status enableProber(grpc::ServerContext *context, const google::protobuf::Empty *request, EnableProberResponse *response) override; /** * 接口 - 停用探针 * @param context 上下文对象,描述了这次远程请求的基础信息(适用:权限验证等) * @param request 请求参数,用于从客户端接收请求数据 * @param response 响应参数,用于向客户端发送响应数据 * @return 函数的执行状态 */ grpc::Status disableProber(grpc::ServerContext *context, const google::protobuf::Empty *request, DisableProberResponse *response) override; ~ProberService() override; }; } // network_prober #endif //NETWORK_PROBER_RPC_PROBER_SERVICE_H std::string a = "在 C++ 中,内存管理是编程的核心之一,而 栈(Stack) 和 堆(Heap) 是两种最常见的内存分配方式。它们各有特点,适用于不同的场景!在 C++ 中,内存管理是编程的核心之一,而 栈(Stack) 和 堆(Heap) 是两种最常见的内存分配方式。它们各有特点,适用于不同的场景!,在 C++ 中,内存管理是编程的核心之一,而 栈(Stack) 和 堆(Heap) 是两种最常见的内存分配方式。它们各有特点,适用于不同的场景!,在 C++ 中,内存管理是编程的核心之一,而 栈(Stack) 和 堆(Heap) 是两种最常见的内存分配方式。它们各有特点,适用于不同的场景!"; std::mutex mutex_a; std::condition_variable condition_a; void t1() { // 上锁 std::unique_lock lock(mutex_a); a = "堆内存需要开发者通过 new/delete 或 malloc/free 显式管理,堆内存需要开发者通过 new/delete 或 malloc/free 显式管理堆内存需要开发者通过 new/delete 或 malloc/free 显式管理,堆内存需要开发者通过 new/delete 或 malloc/free 显式管理 "; condition_a.notify_all(); } void t2() { mutex_a.lock(); // std::cout << a << std::endl; a = "为避免手动管理堆内存的风险,现代 C++ 推荐使用智能指针(如 std::unique_ptr、std::shared_ptr)自动管理堆内存"; mutex_a.unlock(); } void t3() { std::unique_lock lock(mutex_a); // std::cout << a << std::endl; a = "为避免手动管理堆内存的风险,现代 C++ 推荐使用智能指针(如 std::unique_ptr、std::shared_ptr)自动管理堆内存"; mutex_a.unlock(); } void t4() { // mutex_a.lock(); std::cout << a << std::endl; // a = "为避免手动管理堆内存的风险,现代 C++ 推荐使用智能指针(如 std::unique_ptr、std::shared_ptr)自动管理堆内存"; // mutex_a.unlock(); } int main() { std::vector threadPool; threadPool.push_back(std::jthread(t1)); threadPool.push_back(std::jthread(t2)); threadPool.push_back(std::jthread(t3)); threadPool.push_back(std::jthread(t4)); threadPool.clear(); Boost::circular_buffer #include // 针对int类型,构建一个容量为3的循环缓冲区 boost::circular_buffer cb(3); cb.push_back(1); cb.push_back(2); cb.push_back(3); std::cout << "初始缓冲区内容: "; for (size_t i = 0; i < cb.size(); i++) { std::cout << cb[i] << " "; } std::cout << std::endl; cb.push_back(4); cb.push_back(5); std::cout << "覆盖后的内容: "; for (size_t i = 0; i < cb.size(); i++) { std::cout << cb[i] << " "; } std::cout << std::endl; cb.pop_back(); std::cout << "pop_back后的内容: "; for (size_t i = 0; i < cb.size(); i++) { std::cout << cb[i] << " "; } std::cout << std::endl; #include boost::lockfree::queue> queue(5); // 检测是否是真的无锁实现(取决于平台和实现) std::cout << "是否真的无锁实现:" << queue.is_lock_free() << std::endl; // 生产者 std::jthread pro = std::jthread([]() { for (int i = 0; i < 100; i++) { while (!queue.push(i)) { // 队列满时等待 } std::cout << "生产者: " << i << std::endl; } }); // 消费者 std::jthread consu = std::jthread([]() { int value = 0; for (int i = 0; i < 100; i++) { while (!queue.pop(value)) { // 队列空时等待 } std::cout << "消费者:" << value << std::endl; } }); pro.join(); consu.join(); SPDLOG_INFO("正在注册探针..."); // 存储请求的上下文信息 grpc::ClientContext context; // 请求信息 network_perception::rpc::RegisterProbeRequest request; // 基础参数 request.set_version(SysConfig::getInstance().proberVersion()); request.set_machineid(SysConfig::getInstance().proberUUID()); request.set_publicmodel(SysConfig::getInstance().proberPublicModel()); request.set_secretkey(""); // 注册成功后有该值,首次启动留空 // 硬件参数 (对象内存已经开辟) auto requestHardware = request.mutable_hardware(); requestHardware->set_cpumodel(SysConfig::getInstance().proberCPUModel()); requestHardware->set_cpucores(std::to_string(SysConfig::getInstance().proberCPUCores())); requestHardware->set_memorybytes(SysConfig::getInstance().proberMemoryBytes()); requestHardware->set_diskbytes(SysConfig::getInstance().proberDiskBytes()); // 所有物理网卡 auto proberInterfaceConfs = SysConfig::getInstance().proberInterfaceConfs(); for (auto it = proberInterfaceConfs.begin(); it != proberInterfaceConfs.end(); it ++ ) { // 让grpc开辟一块空间 auto requestEthernetInterface = requestHardware->add_nics(); requestEthernetInterface->set_name(it->name); requestEthernetInterface->set_ipv4address(it->IPv4Address); requestEthernetInterface->set_ipv4subnetmask(it->IPv4SubnetMask); requestEthernetInterface->set_ipv4gateway(it->IPv4Gateway); requestEthernetInterface->set_ipv6address(it->IPv6Address); requestEthernetInterface->set_ipv6subnetmask(it->IPv6SubnetMask); requestEthernetInterface->set_ipv6gateway(it->IPv6Gateway); requestEthernetInterface->set_bandwidth(it->bandwidth); requestEthernetInterface->set_macaddress(it->macAddress); } // 响应信息 network_perception::rpc::RegisterProbeResponse response; // 注册探针(同步) grpc::Status ret = m_clientStubPtr->registerProbe(&context, request, &response); if (!ret.ok()) { SPDLOG_ERROR("探针注册失败: {}", ret.error_message()); throw std::runtime_error("探针注册失败..."); } // 响应失败 if (response.code() != RespCode::SUCCESS) { auto errFmt = boost::format("探针注册服务端响应失败: %1%...") % response.msg(); throw std::runtime_error(errFmt.str()); } SPDLOG_INFO("探针注册成功..."); // 将观测目标存入数据表 std::vector observedTargetModels; // 探测任务 auto probeTasks = response.data().probetasks(); for (auto it = probeTasks.begin(); it != probeTasks.end(); it++) { network_prober::database::ObservedTargetModel observedTargetModel; observedTargetModel.interfaceName = it->interfacename(); observedTargetModel.address = it->address(); observedTargetModel.port = it->port(); observedTargetModel.protocol = it->protocol(); observedTargetModel.responseCode = it->responsecode(); observedTargetModel.ignoreTsl = it->ignoretsl(); observedTargetModel.requestMethod = it->requestmethod(); observedTargetModel.requestHeader = it->requestheader(); observedTargetModel.requestBody = it->requestbody(); observedTargetModel.responseChallenge = it->responsechallenge(); observedTargetModel.userName = it->username(); observedTargetModel.password = it->password(); observedTargetModel.databaseName = it->databasename(); observedTargetModel.queryStatement = it->querystatement(); observedTargetModels.emplace_back(observedTargetModel); } // 批量插入观测目标 network_prober::database::MemoryDBHolder::getInstance().batchInsertObservedTargets(observedTargetModels); // 将备份目标存入数据表 std::vector deviceModels; // 观测目标 auto backupTasks = response.data().backuptasks(); for (auto it = backupTasks.begin(); it != backupTasks.end(); it++) { network_prober::database::DeviceModel deviceModel; deviceModel.interfaceName = it->interfacename(); deviceModel.address = it->address(); deviceModel.backupDate = it->backupdate(); deviceModel.command = it->command(); deviceModel.protocol = it->protocol(); deviceModel.account = it->account(); deviceModel.password = it->password(); deviceModel.privilegedPassword = it->privilegedpassword(); deviceModel.port = it->port(); deviceModels.emplace_back(deviceModel); } // 批量插入备份目标 network_prober::database::MemoryDBHolder::getInstance().batchInsertDevices(deviceModels); // 存储探针的secretKey network_prober::sys_config::SysConfig::getInstance().setProberSecretKey(response.data().secretkey()); PerceptionRPCClientInstructionReactor m_clientInstructionReactor; std::unique_ptr m_clientStubPtr; m_clientInstructionReactor.startCall(m_clientStubPtr.get()); // 注册探针(同步) // grpc::Status ret = m_RPCClientStubPtr->registerProbe(&context, request, &response); asio2::ping ping; ping.set_timeout(std::chrono::seconds(4)); ping.set_interval(std::chrono::seconds(1)); ping.bind_init([&]() { std::cout << "=======999999" << std::endl; }); ping.start("www.baidu.com"); SPDLOG_INFO("Hello World: {}", ping.execute("www.baidu.com").milliseconds()); /** * 用于控制协程函数执行的过程 */ class ICMPTargetProbeCoroutine { public: class promise_type { public: ICMPTargetProbeCoroutine get_return_object() { return ICMPTargetProbeCoroutine(std::coroutine_handle::from_promise(*this)); } std::suspend_never initial_suspend() { return {}; } // 协程启动时调用 std::suspend_never final_suspend() noexcept { return {}; } // 协程结束时调用 // std::suspend_always yield_value() { return {}; } // 协程函数中有co_yield时调用 void unhandled_exception() {} // 协程函数发生异常时调用 // void return_void() {} // 协程函数 void return_value(ICMPTargetProbeResult probeResult) // 协程函数中有co_return 有值时调用 { m_probeResult = probeResult; } /** * GCC11bug */ template U&& await_transform(U&& awaitable) noexcept { return static_cast(awaitable); } public: ICMPTargetProbeResult probeResult() { return m_probeResult; } private: ICMPTargetProbeResult m_probeResult; }; /** * 协程对象构造 * @param coroutine */ ICMPTargetProbeCoroutine(std::coroutine_handle coroutine) : coroutineHandle(coroutine) {} public: // 协程promise对象控制 std::coroutine_handle coroutineHandle; }; class ICMPTargetProbeTask { public: ICMPTargetProbeTask(const std::string& interfaceName, const std::string& address) : m_interfaceName(interfaceName), m_address(address) { // 一次请求的超时时间(秒) m_ping.set_timeout(std::chrono::seconds(10)); // 每隔多久请求一次 m_ping.set_interval(std::chrono::seconds(15)); // socket初始化时回调 m_ping.bind_init([&]() { asio::ip::address_v4 interfaceAddress = asio::ip::address_v4::from_string("192.168.0.108"); m_ping.socket().set_option(asio::ip::multicast::outbound_interface(interfaceAddress)); }); // 请求开始回调 m_ping.bind_start([](){ if (asio2::get_last_error()) std::cout << asio2::last_error_msg() << std::endl; }); // m_ping.socket() // asio2::ping::execute() // 响应超时,或响应正常时回调 m_ping.bind_recv([&](asio2::icmp_rep& rep) { if (rep.is_timeout()) { m_timeConsumingInMilliSeconds = -1; std::cout << "request timed out" << std::endl; } else { m_timeConsumingInMilliSeconds = rep.milliseconds(); std::cout << rep.total_length() - rep.header_length() << " bytes from " << rep.source_address() << " to " << rep.destination_address() << ": icmp_seq=" << rep.sequence_number() << ", ttl=" << rep.time_to_live() << ", time=" << rep.milliseconds() << "ms" << std::endl; // 让协程继续执行 // handle.resume(); } // m_ping // 响应后,停止再发送请求 m_ping.stop(); m_coroutine.resume(); SPDLOG_DEBUG("11111"); }); m_ping.bind_stop([&]() { // m_coroutine.resume(); }); } /** * 任务是否需要执行await_suspend() * @return false 表示未准备好,需要暂停 */ bool await_ready() { return false; } /** * 在协程暂停后,执行的方法 * @param handle 协程promise对象句柄 */ void await_suspend(std::coroutine_handle<> handle) { m_coroutine = handle; m_ping.start(m_address); } /** * co_await 输出的值 * 这里用于返回延迟的时间 */ ICMPTargetProbeResult await_resume() { return ICMPTargetProbeResult{.interfaceName = m_interfaceName, .address = m_address, .timeConsumingInMilliSeconds = m_timeConsumingInMilliSeconds}; } private: std::coroutine_handle<> m_coroutine; asio2::ping m_ping{}; long m_timeConsumingInMilliSeconds{0}; std::string m_address; std::string m_interfaceName; }; /** * 协程函数 * 特征:返回值的类型是协程函数 */ ICMPTargetProbeCoroutine executeICMPTargetProbeTask(const std::string& interfaceName, const std::string& address) { // 新建 ICMP目标 探测任务 ICMPTargetProbeTask probeTask{interfaceName, address}; // 执行探测任务 // ICMPTargetProbeResult probeResult(); ICMPTargetProbeResult probeResult = co_await probeTask; // co_await 一个对象时,该对象需要实现系列特定方法 // SPDLOG_INFO("探测耗时:{}s", probeResult.timeConsumingInMilliSeconds * 1000); // 返回探测耗时 co_return probeResult; } // 不断查看观测协程是否执行完毕 // 标志位,协程是否都完成 bool probeTasksDone = true; while (1) { probeTasksDone = true; for (const auto& probeCoroutine : probeCoroutines) { probeTasksDone &= probeCoroutine.coroutineHandle.done(); } if (probeTasksDone) break; } // 设定负载 boost::json::array data; for (const auto& probeCoroutine : probeCoroutines) { auto probeResult = probeCoroutine.coroutineHandle.promise().probeResult(); auto jsonProbeResult = boost::json::value_from(probeResult); data.push_back(jsonProbeResult); } // 构建ping对象 asio2::ping ping; // 一次ping的超时时间 ping.set_timeout(std::chrono::seconds(15)); // 两次ping之间的间隔时间 ping.set_interval(std::chrono::seconds(20)); // 在socket初始化时调用 ping.bind_init([&]() { asio::ip::address_v4 interfaceAddress = asio::ip::address_v4::from_string("192.168.0.108"); ping.socket().set_option(asio::ip::multicast::outbound_interface(interfaceAddress)); }); // 响应时调用 ping.bind_recv([&](asio2::icmp_rep& rep) { { // 加锁 std::unique_lock probeResultsLock(probeResultsMutx); // 收集探测结果 probeResults.emplace_back(interfaceName.c_str(), address, rep.is_timeout()? -1 : rep.milliseconds()); // 通知解锁 probeResultsCv.notify_one(); } // 停止探测 ping.stop(); }); // 开始ping时调用 ping.bind_start([](){ if (asio2::get_last_error()) std::cout << asio2::last_error_msg() << std::endl; }); // 发起请求 ping.start(address); ping.execute(""); // 收集ping请求 pings.push_back(std::move(ping)); // ICMP协议 if (ProbeDetectProtocol::ICMP == static_cast(protocol)) { } // // TCP协议 // else if (ProbeDetectProtocol::TCP == static_cast(protocol)) { // // 遍历设备ip,发送探测请求 // for (const std::string& addressIP : addressIPVec) { // // } // } // // UDP协议 // else if (ProbeDetectProtocol::UDP == static_cast(protocol)) { // // 遍历设备ip,发送探测请求 // for (const std::string& addressIP : addressIPVec) { // // } // } // // 响应时调用 // m_UDPClient.bind_recv([this, self](std::string_view data) { // std::cout << "FFFFFFFFFFFFFFFFFF" << std::endl; // // 睡眠一段时间,在释放 // std::this_thread::sleep_for(std::chrono::seconds(1)); // // 停止探测 // m_UDPClient.stop(); // // // 该代码块执行完, self被释放,当前对象计数器减1.释放当前对象 // }); // 抛出异常 // 返回结果 std::future future = std::async(std::launch::async, [&]() -> int { // throw std::runtime_error(""); std::this_thread::sleep_for(std::chrono::seconds(5)); std::cout << "异步执行的任务..." << std::endl; return 100; }); std::cout << "任务执行..." << std::endl; try { // <阻塞等待>任务函数执行结束,并得到结果 int ret = future.get(); std::cout << ret << std::endl; } catch (const std::exception& e) { std::cout << e.what() << std::endl; } // 都是从数据中取出的,对象的类型应该一样 构造出不同的类型,再发送? // 创建一个 ping 发送器 // asio2::ping ping; // // // 设置响应等待时长 // ping.set_timeout(std::chrono::seconds(4)); // // 设置两次发送的时间间隔 // ping.set_interval(std::chrono::seconds(1)); // // SPDLOG_DEBUG("main"); // // // // ping.bind_init([&]() { // SPDLOG_DEBUG("bind_init"); // // asio::ip::address_v4 interfaceAddress = asio::ip::address_v4::from_string("127.0.0.1"); // ping.socket().set_option(asio::ip::multicast::outbound_interface(interfaceAddress)); // }); // // ping.bind_start([](){ // SPDLOG_DEBUG("bind_start"); // // if (asio2::get_last_error()) // std::cout << asio2::last_error_msg() << std::endl; // }); // // ping.bind_recv([](asio2::icmp_rep& rep) { // SPDLOG_DEBUG("bind_recv"); // // std::this_thread::sleep_for(std::chrono::seconds(8)); // // if (rep.is_timeout()) // std::cout << "request timed out" << std::endl; // else // std::cout << rep.total_length() - rep.header_length() // << " bytes from " << rep.source_address() // << " to " << rep.destination_address() // << ": icmp_seq=" << rep.sequence_number() // << ", ttl=" << rep.time_to_live() // << ", time=" << rep.milliseconds() << "ms" // << std::endl; // }); // // auto startTime = std::chrono::system_clock::now(); // // // 开始发送 ping 给 host (经测试,平均发送1个请求耗时为3ms以内) // ping.start("www.baidu.com"); // ipv4 if (1) { SPDLOG_INFO("开始调用协程咯.."); // 记录观测延迟 std::array probeDelays; // 依次进行4次观测 std::size_t probeTimes = probeDelays.size(); for (std::size_t i = 0; i < probeTimes; i++) { // 观测封装对象 HandleICMPProbeIPv4Awaiter awaiter; // 发起观测 probeDelays[i] = co_await awaiter; } SPDLOG_INFO("协程调用完,准备返回了.."); // 返回观测延迟 co_return probeDelays; } // ipv6 else if (0) { } // std::cout << sizeof(unsigned int) << std::endl; fd00:7860:5bfc:44d0:2e2:69ff:fe44:f52f // std::cout << asio2::ping_ipv6::execute("fd00:7860:5bfc:44d0:2e2:69ff:fe44:f52f").milliseconds() << std::endl; // // std::cout << asio2::last_error_msg() << std::endl; // std::cout << asio2::ping_ipv4::execute("192.168.0.151").milliseconds() << std::endl; // 都是从数据中取出的,对象的类型应该一样 构造出不同的类型,再发送? // 创建一个 ping 发送器 asio2::ping_ipv6 ping; // 设置响应等待时长 ping.set_timeout(std::chrono::seconds(4)); // 设置两次发送的时间间隔 ping.set_interval(std::chrono::seconds(1)); SPDLOG_DEBUG("main"); std::cout << "Hello World!\n" << std::endl; // ping.bind_init([&]() { std::cout << "MMMMM" << std::endl; SPDLOG_DEBUG("bind_init"); auto localEndpointAddress = asio::ip::address::from_string("fd00:7860:5bfc:44d0:1de9:be6a:9f90:7f83"); ping.socket().bind(asio::ip::icmp::endpoint(localEndpointAddress, 0)); }); ping.bind_start([](){ SPDLOG_DEBUG("bind_start"); if (asio2::get_last_error()) std::cout << asio2::last_error_msg() << std::endl; }); ping.bind_recv([](asio2::icmpv6_rep& rep) { SPDLOG_DEBUG("bind_recv"); std::cout << "延迟为:" << rep.milliseconds() << std::endl; // std::this_thread::sleep_for(std::chrono::seconds(8)); if (rep.is_timeout()) std::cout << "request timed out" << std::endl; // else // std::cout << rep.total_length() - rep.header_length() // << " bytes from " << rep.source_address() // << " to " << rep.destination_address() // << ": icmp_seq=" << rep.sequence_number() // << ", ttl=" << rep.time_to_live() // << ", time=" << rep.milliseconds() << "ms" // << std::endl; }); // 开始发送 ping 给 host (经测试,平均发送1个请求耗时为3ms以内) ping.start("fd00:7860:5bfc:44d0:2e2:69ff:fe44:f52f"); while (std::getchar() != '\n'); ping.stop(); printf("loss rate : %.0lf%% average time : %ldms\n", ping.plp(), long(std::chrono::duration_cast(ping.avg_lag()).count())); while (std::getchar() != '\n'); // 数据库 // m_db = duckdb_database(); // // 数据库连接 // duckdb_connection conn; // // 查询结果 // duckdb_result result; // // // 连接数据库 conn // if (duckdb_connect(db, &conn) == DuckDBError) { // std::cout << "DuckDB Connect Error" << std::endl; // duckdb_destroy_result(&result); // duckdb_disconnect(&conn); // duckdb_close(&db); // return -1; // } // // // 执行SQL,创建表 // if (duckdb_query(conn, "CREATE TABLE integers(i INTEGER, j INTEGER);", NULL) == DuckDBError) { // fprintf(stderr, "Failed to query database\n"); // duckdb_destroy_result(&result); // duckdb_disconnect(&conn); // duckdb_close(&db); // return -1; // } // // // 执行SQL,向表里插入数据 // if (duckdb_query(conn, "INSERT INTO integers VALUES (3, 4), (5, 6), (7, NULL);", NULL) == DuckDBError) { // fprintf(stderr, "Failed to query database\n"); // duckdb_destroy_result(&result); // duckdb_disconnect(&conn); // duckdb_close(&db); // } // // // 执行SQL,从表里查询数据 // if (duckdb_query(conn, "SELECT * FROM integers", &result) == DuckDBError) { // fprintf(stderr, "Failed to query database\n"); // duckdb_destroy_result(&result); // duckdb_disconnect(&conn); // duckdb_close(&db); // } // // // print the names of the result // idx_t row_count = duckdb_row_count(&result); // idx_t column_count = duckdb_column_count(&result); // for (size_t i = 0; i < column_count; i++) { // printf("%s ", duckdb_column_name(&result, i)); // } // printf("\n"); // // print the data of the result // for (size_t row_idx = 0; row_idx < row_count; row_idx++) { // for (size_t col_idx = 0; col_idx < column_count; col_idx++) { // char *val = duckdb_value_varchar(&result, col_idx, row_idx); // printf("%s ", val); // duckdb_free(val); // } // printf("\n"); // } // // duckdb_destroy_result(&result); // duckdb_disconnect(&conn); // duckdb_close(&db); // int rc = libssh2_init(0); // if (!rc) { // std::cerr << "libssh2_init failed" << std::endl; // } // // std::string_view host = "127.0.0.1"; // std::string_view port = "8080"; // // std::string s{host}; // // std::cout << s << std::endl; // // std::string json = R"()"; // // auto o = boost::json::parse(json);//.if_object(); // // // if (o != nullptr) { // // for (auto it = o->begin(); it != o->end(); ++it) { // // std::cout << it->key() << ": " << it->value() << std::endl; // // } // // } // // std::cout << json << std::endl; // // asio2::socks5::option // sock5_option{ "127.0.0.1",10808 }; // //asio2::socks5::option // // sock5_option{ "s5.doudouip.cn",1088,"zjww-1","aaa123" }; // // // download and save the file directly. // see ssl_http_client.cpp // // The file is in this directory: /asio2/example/bin/x64/100mb.test // // asio2::http_client::download("http://cachefly.cachefly.net/100mb.test", "100mb.test"); // // std::string_view url = R"(http://www.baidu.com/cond?json={"qeury":"name like '%abc%'","id":1})"; // std::string en = http::url_encode(url); // std::cout << en << std::endl; // std::string de = http::url_decode(en); // std::cout << de << std::endl; // // auto path = asio2::http::url_to_path(url); // std::cout << path << std::endl; // // // auto query = asio2::http::url_to_query(url); // std::cout << query << std::endl; // // auto h = asio2::http::url_to_host(url); // std::cout << h << std::endl; // // auto p = asio2::http::url_to_port(url); // std::cout << p << std::endl; // // // auto rep21 = asio2::http_client::execute(url); // std::cout << rep21 << std::endl; // // http::web_request req24 = http::make_request(url); // req24.set(http::field::user_agent, "Chrome"); // auto rep26 = asio2::http_client::execute(req24); // std::cout << rep26 << std::endl; // // // asio2::http_client::execute("www.baidu.com", "80", "/", std::chrono::seconds(5)); // asio2::http_client::execute("www.baidu.com", "80", "/", sock5_option); // // // // GET // auto req2 = http::make_request("GET / HTTP/1.1\r\nHost: 192.168.0.1\r\n\r\n"); // auto rep2 = asio2::http_client::execute("www.baidu.com", "80", req2, std::chrono::seconds(3)); // if (asio2::get_last_error()) // std::cout << asio2::last_error_msg() << std::endl; // else // std::cout << rep2 << std::endl; // // // POST // http::make_request(); http::web_request req4 = http::make_request("POST / HTTP/1.1\r\nHost: 192.168.0.1\r\n\r\n"); // auto rep4 = asio2::http_client::execute("www.baidu.com", "80", req4); // if (asio2::get_last_error()) // std::cout << asio2::last_error_msg() << std::endl; // else // std::cout << rep4 << std::endl; // // // GET // http::web_request req6(http::verb::get, "/", 11); // req6.set(http::field::user_agent, "Chrome"); // auto rep6 = asio2::http_client::execute("www.baidu.com", "80", req6, sock5_option); // if (asio2::get_last_error()) // std::cout << asio2::last_error_msg() << std::endl; // else // std::cout << rep6 << std::endl; // // // POST // http::web_request req7; // req7.method(http::verb::post); // req7.target("/"); // req7.set(http::field::user_agent, "Chrome"); // req7.set(http::field::content_type, "text/html"); // req7.body() = "Hello World."; // req7.prepare_payload(); // auto rep7 = asio2::http_client::execute("www.baidu.com", "80", req7); // if (asio2::get_last_error()) // std::cout << asio2::last_error_msg() << std::endl; // else // std::cout << rep7 << std::endl; // // // convert the response body to string // std::stringstream ss1; // ss1 << rep7.body(); // std::cout << ss1.str() << std::endl; // // // convert the whole response to string // std::stringstream ss2; // ss2 << rep7; // std::cout << ss2.str() << std::endl; // host = "www.baidu.com"; // port = "80"; // // asio2::http_client client; // // client.bind_connect([&]() // { // if (asio2::get_last_error()) // printf("connect failure : %d %s\n", // asio2::last_error_val(), asio2::last_error_msg().c_str()); // else // printf("connect success : %s %u\n", // client.local_address().c_str(), client.local_port()); // // // connect success, send a request. // if (!asio2::get_last_error()) // { // // http::web_request req4 = http::make_request("POST / HTTP/1.1\r\nHost: 192.168.0.1\r\n\r\n"); // // req4.set(http::field::body, "Hello World"); // // req4.version(http::field::ho) // // req4.set(http::field::protocol, "text/html"); // // req4.set(http::field::authorization, "basic "); // // req4.set(http::field::user_agent, "Chrome"); // // // // req4.body(); // // client.bind_recv([&](http::web_request& req, http::web_response& rep) // { // // print the whole response // std::cout << rep << std::endl; // // // print the response body // std::cout << rep.body() << std::endl; // // // convert the response body to string // std::stringstream ss; // ss << rep.body(); // std::cout << ss.str() << std::endl; // // // Remove all fields // req.clear(); // // req.set(http::field::user_agent, "Chrome"); // req.set(http::field::content_type, "text/html"); // // // http::verb::post // // req.method(http::verb::get); // req.keep_alive(true); // req.target("/get_user?name=abc"); // req.body() = "Hello World."; // req.prepare_payload(); // // client.async_send(std::move(req)); // // }); // // // const char * msg = "GET / HTTP/1.1\r\n\r\n"; // // client.async_send(msg); // // http::web_request req = http::make_request(url); // client.async_send(std::move(req)); // } // }); // // // client.start(); // // client.async_start(host, port/*, sock5_option*/); // // while (std::getchar() != '\n'); std::getline(file, line); // CPUInfo cpuInfo; std::vector fields; std::string field; std::istringstream iss{line}; // iss >> cpuInfo.name >> cpuInfo.user >> cpuInfo.nice >> cpuInfo.system; while (iss >> field) { fields.push_back(field); } // iss >> long user = std::stol(fields[1]); long nice = std::stol(fields[2]); long system = std::stol(fields[3]); long idle = std::stol(fields[4]); long iowait = std::stol(fields[5]); long irq = std::stol(fields[6]); long softirq = std::stol(fields[7]); long total = user + nice + system + idle + iowait + irq + softirq; long idle_total = idle; file.close(); std::this_thread::sleep_for(std::chrono::seconds(1)); std::ifstream file1("/proc/stat"); std::string line1; std::getline(file1, line1); std::vector fields1; std::string field1; std::istringstream iss1{line1}; while (iss1 >> field1) { fields1.push_back(field1); } long user1 = std::stol(fields1[1]); long nice1 = std::stol(fields1[2]); long system1 = std::stol(fields1[3]); long idle1 = std::stol(fields1[4]); long iowait1 = std::stol(fields1[5]); long irq1 = std::stol(fields1[6]); long softirq1 = std::stol(fields1[7]); long total1 = user1 + nice1 + system1 + idle1 + iowait1 + irq1 + softirq1; long idle_total1 = idle1; std::uint8_t r = static_cast((total1 - idle_total1) - (total - idle_total)) / (total1 - total) * 100; std::cout << std::oct << r << std::endl; std::cout << "HHHH" << std::endl; std::ifstream file("/proc/meminfo"); std::unordered_map cpu_info_map; std::string key; std::uint64_t value; while (file >> key >> value) { cpu_info_map[key] = value; file.ignore(256, '\n'); } for (auto it = cpu_info_map.begin(); it != cpu_info_map.end(); ++it) { std::cout << it->first << ": " << it->second << std::endl; } std::cout << "JJJJJ" << std::endl; int mfunc(int a, int b) { std::cout << __FUNCTION__ << "\n"; return a + b; } class F { public: int mfunc(int a, int b) { std::cout << __FUNCTION__ << "\n"; return a + b; } }; struct CPUInfo { std::string name; std::uint32_t user; std::uint32_t nice{}; std::uint32_t system{}; std::uint32_t idle{}; std::uint32_t iowait{}; std::uint32_t irq{}; std::uint32_t softirq{}; std::uint32_t steal{}; std::uint32_t guest{}; std::uint32_t guest_nice; }; std::filesystem::path path{"/"}; std::filesystem::space_info space = std::filesystem::space(path); std::cout << "Total space: " << space.capacity << std::endl; std::cout << "Free space: " << space.free << std::endl; std::cout << "Used space: " << (space.capacity - space.free) << std::endl; // std::future f = std::async(std::launch::async, mfunc, 20, 30); // // F cf; // // std::async(std::launch::async, &F::mfunc, &cf, 10, 20); // // std::cout << f.get() << "\n"; // // 事件容器 // asio::io_context ioCtx; // // asio::ip::tcp::resolver resolver(ioCtx); // // asio::error_code ec; // // auto endpoints = resolver.resolve("www.baidu.com", "", ec); // // if (ec) { // std::cout << "Error: " << ec.message() << "\n"; // } // // for (auto it = endpoints.begin(); it != endpoints.end(); ++it) { // std::cout << it->endpoint().address().to_string() << std::endl; // } // // ip::tcp::socket socket(ioCtx); // asio::connect(socket, endpoints); // 本质上是一个tcp_socket // boost::asio::ip::tcp::acceptor acceptor(ioCtx); // 事件循环 // ioCtx.run(); // while (std::getchar() != '\n'); // try // { // // if (argc != 3) // // { // // std::cerr << "Usage: client \n"; // // return 1; // // } // // asio::io_context io_context; // // asio2::error_code errorCode; // // tcp::resolver resolver(io_context); // auto endpoints = resolver.resolve("www.jjwxc.net", "443", errorCode); // // asio::ssl::context ctx{asio::ssl::context::tlsv12_client}; // ctx.load_verify_file("ca.pem"); // ctx.set_verify_mode(asio::ssl::verify_peer); // // client c(io_context, ctx, endpoints); // // io_context.run(); // } // catch (std::exception& e) // { // std::cerr << "Exception: " << e.what() << "\n"; // } auto elements4 = asio2::https_client::execute("https://www.baidu.com"); std::cout << " 4 " << std::endl; std::cout << elements4.base().result() << std::endl; std::cout << elements4.base().reason() << std::endl; // asio::ssl::context ctx{ asio::ssl::context::tlsv12_client }; // ctx.set_verify_mode(asio::ssl::context::verify_peer); // ctx.load_verify_file("ca.pem"); // http::web_request req1; // auto elements = asio2::https_client::execute(ctx, "www.jjwxc.net", "443", req1, std::chrono::seconds(3)); // // std::cout << elements.base().result() << std::endl; // std::cout << elements.base().reason() << std::endl; // // // asio2::https_client::execute(ctx, "www.baidu.com", "443", req1); // // auto m = asio2::https_client::execute("www.jjwxc.net", "443", req1, std::chrono::seconds(5)); // // std::cout << m.base().result() << std::endl; // std::cout << m.base().reason() << std::endl; // // asio2::https_client::execute("www.baidu.com", "443", req1); // // asio2::https_client client; // // // client.set_options(asio::ssl::context::no_compression); // client.set_auto_reconnect(false); // client.set_verify_mode(asio::ssl::verify_peer); // // client.set_verify_callback([](bool preverified, // asio::ssl::verify_context& ctx) -> bool { // return preverified; // }); // // // // client.set_cert_file( // "ca.crt", // "client.crt", // "client.key", // "123456"); // // if (asio2::get_last_error()) // std::cout << "load cert files failed: " << asio2::last_error_msg() << std::endl; // // client.set_connect_timeout(std::chrono::seconds(10)); // // client.bind_recv([&](http::web_request& req, http::web_response& rep) // { // asio2::ignore_unused(req); // // std::cout << "----------------------------------------" << std::endl; // std::cout << rep << std::endl; // // }).bind_connect([&]() // { // if (asio2::get_last_error()) // printf("connect failure : %d %s\n", // asio2::last_error_val(), asio2::last_error_msg().c_str()); // else // printf("connect success : %s %u\n", // client.local_address().c_str(), client.local_port()); // // // send a request // client.async_send("GET / HTTP/1.1\r\n\r\n"); // // }).bind_disconnect([]() // { // printf("disconnect : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str()); // }).bind_handshake([&]() // { // printf("handshake : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str()); // }); // // if (!client.start("www.twetec.com", "443")) // { // std::cout << "start failed : " << asio2::last_error_msg() << std::endl; // } // else // { // std::cout << "start success " << std::endl; // } // // // send data, beacuse may be connect failed, // // if connect failed, the data will sent failed too. // client.async_send(std::string("abc0123456789xyz"), []() // { // if (asio2::get_last_error()) // std::cout << "send failed : " << asio2::last_error_msg() << std::endl; // }); while (std::getchar() != '\n'); // using asio::ip::tcp; // using std::placeholders::_1; // using std::placeholders::_2; // // enum { max_length = 1024 }; // // class client // { // public: // client(asio::io_context& io_context, // asio::ssl::context& context, // const tcp::resolver::results_type& endpoints) // : socket_(io_context, context) // { // socket_.set_verify_mode(asio::ssl::verify_peer); // socket_.set_verify_callback( // std::bind(&client::verify_certificate, this, _1, _2)); // // connect(endpoints); // } // // private: // bool verify_certificate(bool preverified, // asio::ssl::verify_context& ctx) // { // // The verify callback can be used to check whether the certificate that is // // being presented is valid for the peer. For example, RFC 2818 describes // // the steps involved in doing this for HTTPS. Consult the OpenSSL // // documentation for more details. Note that the callback is called once // // for each certificate in the certificate chain, starting from the root // // certificate authority. // // // In this example we will simply print the certificate's subject name. // char subject_name[256]; // X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle()); // X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256); // std::cout << "Verifying " << subject_name << "\n"; // // return preverified; // } // // void connect(const tcp::resolver::results_type& endpoints) // { // asio::async_connect(socket_.lowest_layer(), endpoints, // [this](const asio2::error_code& error, // const tcp::endpoint& /*endpoint*/) // { // if (!error) // { // handshake(); // } // else // { // std::cout << "Connect failed: " << error.message() << "\n"; // } // }); // } // // void handshake() // { // socket_.async_handshake(asio::ssl::stream_base::client, // [this](const asio2::error_code& error) // { // if (!error) // { // send_request(); // } // else // { // std::cout << "Handshake failed: " << error.message() << "\n"; // } // }); // } // // void send_request() // { // std::cout << "Enter message: "; // std::cin.getline(request_, max_length); // size_t request_length = std::strlen(request_); // // asio::async_write(socket_, // asio::buffer(request_, request_length), // [this](const asio2::error_code& error, std::size_t length) // { // if (!error) // { // receive_response(length); // } // else // { // std::cout << "Write failed: " << error.message() << "\n"; // } // }); // } // // void receive_response(std::size_t length) // { // asio::async_read(socket_, // asio::buffer(reply_, length), // [this](const asio2::error_code& error, std::size_t length) // { // if (!error) // { // std::cout << "Reply: "; // std::cout.write(reply_, length); // std::cout << "\n"; // } // else // { // std::cout << "Read failed: " << error.message() << "\n"; // } // }); // } // // asio::ssl::stream socket_; // char request_[max_length]; // char reply_[max_length]; // }; #ifndef ASIO2_ENABLE_SSL #define ASIO2_ENABLE_SSL #endif #include timedatectl set-ntp no // #include #include "network_prober/probe/probe_task_handler.h" // using namespace boost::asio; // // class Session : public std::enable_shared_from_this // 在类内部延长生命周期 // { // public: // Session(ip::tcp::socket socket) // : m_socket(std::move(socket)) // { // // } // // void start() // { // _doRead(); // } // // private: // void _doClose() // { // boost::system::error_code ec; // m_socket.close(ec); // } // // void _doRead() // { // // 在对象内部,将当前对象的引用计数值加1 // auto self(shared_from_this()); // m_socket.async_read_some(buffer(m_readBuffer, MAX_PACKET_LEN), [this, self](boost::system::error_code ec, std::size_t bytes_transferred) { // if (ec) { // _doClose(); // return; // } // _doRead(); // }); // } // // void _doWrite() // { // auto self(shared_from_this()); // m_socket.async_write_some(buffer(m_readBuffer, MAX_PACKET_LEN), [this, self](boost::system::error_code ec, std::size_t bytes_transferred) { // if (ec) { // _doClose(); // return; // } // // _doRead(); // }); // } // // private: // ip::tcp::socket m_socket; // enum { MAX_PACKET_LEN = 1024 }; // char m_readBuffer[MAX_PACKET_LEN]; // }; // // class Server // { // public: // Server(io_context& ioCtx, std::uint16_t port) // : m_acceptor(ioCtx, ip::tcp::endpoint(ip::tcp::v4(), port)) // { // // } // // private: // void doAccept() // { // m_acceptor.async_accept([this](boost::system::error_code ec, ip::tcp::socket sock) { // if (!ec) { // std::make_shared(std::move(sock))->start(); // } // }); // } // // private: // ip::tcp::acceptor m_acceptor; // }; // #include // // 初始化libssh2库,在应用程序启动时,只调用一次 int rc = libssh2_init(0); if (rc != 0) { std::cout << "libssh2 initialization failed" << std::endl; } // 创建socket(套接字) int socketfd = socket(AF_INET, SOCK_STREAM, 0); if (socketfd < 0) { std::cout << "socket() failed" << std::endl; return -1; } // 设定本地网卡地址 struct sockaddr_in localEndpoint; memset(&localEndpoint, 0, sizeof(struct sockaddr_in)); localEndpoint.sin_family = AF_INET; localEndpoint.sin_addr.s_addr = inet_addr("192.168.0.108"); localEndpoint.sin_port = 0; // 绑定本地网卡 if (bind(socketfd, reinterpret_cast(&localEndpoint), sizeof(struct sockaddr_in))) { std::cout << "bind() failed" << std::endl; return -1; } // 设定目标连接地址(类似于asio的endpoint) struct sockaddr_in targetEndpoint; memset(&targetEndpoint, 0, sizeof(struct sockaddr_in)); targetEndpoint.sin_family = AF_INET; targetEndpoint.sin_port = htons(22); targetEndpoint.sin_addr.s_addr = inet_addr("192.168.0.151"); // 连接目标地址 if (connect(socketfd, reinterpret_cast(&targetEndpoint), sizeof(struct sockaddr_in))) { std::cout << "connect() failed" << std::endl; return -1; } // 使用ssh协议连接到远程主机 LIBSSH2_SESSION* session = libssh2_session_init_ex(NULL, NULL, NULL, NULL); if (!session) { std::cout << "libssh2 session initialization failed" << std::endl; return -1; } // 在debug模式下,输出调试日志 libssh2_trace(session, ~0); if (rc = libssh2_session_handshake(session, socketfd)) { std::cout << "libssh2_session_handshake() failed: " << rc << std::endl; return -1; } rc = 1; /* At this point we have not yet authenticated. The first thing to do * is check the hostkey's fingerprint against our known hosts Your app * may have it hard coded, may go to a file, may present it to the * user, that's your call */ const char *fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); fprintf(stderr, "Fingerprint: "); for(int i = 0; i < 20; i++) { fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]); } fprintf(stderr, "\n"); const char* username = "ubuntu"; const char* password = "!QAZ2wsx@123"; /* check what authentication methods are available */ // userauthlist: publickey,password char* userauthlist = libssh2_userauth_list(session, username, (unsigned int)strlen(username)); std::cout << "userauthlist: " << userauthlist << std::endl; // 如果不包含密码验证模式 if (!strstr(userauthlist, "password")) { std::cout << "不包含密码验证模式" << std::endl; return -1; } // 帐号和密码验证 rc = libssh2_userauth_password(session, username, password); if (rc != 0) { std::cout << "用户名密码验证失败。。" << std::endl; } std::cout << "成功" << std::endl; /* Request a session channel on which to run a shell */ LIBSSH2_CHANNEL *channel = libssh2_channel_open_session(session); if(!channel) { fprintf(stderr, "Unable to open a session\n"); return -1; } // 设置会话的阻塞与非阻塞模式 libssh2_session_set_blocking(session, 1); if(libssh2_channel_request_pty(channel, "vanilla")) { fprintf(stderr, "Failed requesting pty\n"); } // if(libssh2_channel_exec(channel, "uname -r\n ls -la\n pwd\n date")) { // fprintf(stderr, "Unable to request command on channel\n"); // return -1; // } if(libssh2_channel_shell(channel)) { fprintf(stderr, "Unable to request shell on allocated pty\n"); return -1; } char b[1024*8]; libssh2_channel_read(channel, b, sizeof(b)); std::cout << "cmd: " << b << std::endl; const char* cmd = "ls"; libssh2_channel_write(channel, cmd, sizeof(cmd)); libssh2_channel_read(channel, b, sizeof(b)); std::cout << "cmd: " << b << std::endl; // while(!libssh2_channel_eof(channel)) { // char buf[1024]; // ssize_t err = libssh2_channel_read(channel, buf, sizeof(buf)); // if(err < 0) // fprintf(stderr, "Unable to read response: %ld\n", (long)err); // else { // fwrite(buf, 1, (size_t)err, stdout); // } // } rc = libssh2_channel_get_exit_status(channel); if(libssh2_channel_close(channel)) fprintf(stderr, "Unable to close channel\n"); if(channel) { libssh2_channel_free(channel); channel = NULL; } if(session) { libssh2_session_disconnect(session, "Normal Shutdown"); libssh2_session_free(session); } if(socketfd != LIBSSH2_INVALID_SOCKET) { shutdown(socketfd, 2); LIBSSH2_SOCKET_CLOSE(socketfd); } // 在使用完libssh2库后,清理分配的资源 libssh2_exit(); GOOS=linux GOARCH=amd64 CGO_ENABLED // std::ignore = std::async(std::launch::async, [] -> void { // try { // // mysql // // soci::session sql(soci::mysql, "host=192.168.0.102 port=3306 user=root password='root' dbname=datax_web bind_address='192.168.0.108'"); // // // // // postgrepsql // // soci::session sql(soci::postgresql, "host=192.168.0.102 port=5432 user=postgres password='root' dbname=ganzhi"); // // // sql server // // soci::session sql(soci::odbc, "DSN=ODBC;UID=sa;PWD=sa123;Connection Driver=TDS;Database=ReportServer;Server=192.168.1.52;Port=1433;"); // // // 查询记录 // // MySQL // // sql.once << "SELECT * FROM sys_user"; // // // postgrepsql // // sql.once << "SELECT * FROM asset_mapping"; // // // 打印表头 // // const soci::row& header = rs.get_metadata(); // // for (std::size_t i = 0; i != header.size(); ++i) { // // std::cout << header.get_properties(i).get_name() << "\t"; // // } // // std::cout << std::endl; // // // 遍历每行记录 // // for (const soci::row& it : rs) { // // // 遍历一行记录的每个字段 // // for (std::size_t i = 0; i != it.size(); ++i) { // // // 获取当前行记录的第i个字段属性 // // const soci::column_properties& columnProperties = it.get_properties(i); // // // // // 根据字段属性中的类型,转化为特定值 // // switch (columnProperties.get_db_type()) { // // case soci::db_string: // // std::cout << it.get(i) << std::endl; // 读取当前行的第i个字段的值,并将值转换为对应类型 // // break; // // case soci::db_int64: // // std::cout << it.get(i) << std::endl; // // break; // // default: // // break; // // } // // // // // if (it.get_indicator(i) == soci::i_null) { // // // std::cout << "NULL\t"; // // // } else { // // // if (i == 2) { // // // std::cout << it.get(i) << std::endl; // // // } // // // else { // // // std::cout << it.get(i) << std::endl; // // // } // // // } // // } // // // std::cout << std::endl; // // } // } // catch (const soci::soci_error& e) { // std::cerr << "错误:" << e.what() << std::endl; // } // }); MYSQL* mysqlPtr = mysql_init(NULL); // 设置字符编码 mysql_options(mysqlPtr, MYSQL_SET_CHARSET_NAME, "utf8"); // 设置客户端网口 mysql_options(mysqlPtr, MYSQL_OPT_BIND, "192.168.0.108"); // 设置自动重连 mysql_options(mysqlPtr, MYSQL_OPT_CONNECT_TIMEOUT, "10"); const char* unixSocket = NULL; // 连接数据库 MYSQL* connPtr = mysql_real_connect(mysqlPtr, "192.168.0.102", "root", "root", "datax_web", 3306, unixSocket, 0); if (connPtr == NULL) { std::cout << "数据库连接失败: " << mysql_error(mysqlPtr) << std::endl; } const char* sql = "SELECT 1"; std::int32_t res = mysql_query(connPtr, sql); if (res != 0) { std::cout << "数据库查询失败: " << mysql_error(connPtr) << std::endl; } std::cout << res << std::endl; // 关闭数据库连接 mysql_close(connPtr); // // 创建socket(套接字) // int socketfd = socket(AF_INET, SOCK_STREAM, 0); // if (socketfd < 0) { // std::cout << "socket() failed" << std::endl; // return -1; // } // // // 设定本地网卡地址 // // struct sockaddr_in localEndpoint; // // memset(&localEndpoint, 0, sizeof(struct sockaddr_in)); // // localEndpoint.sin_family = AF_INET; // // localEndpoint.sin_addr.s_addr = inet_addr("192.168.0.108"); // // localEndpoint.sin_port = 0; // // // 绑定本地网卡 // // if (bind(socketfd, reinterpret_cast(&localEndpoint), sizeof(struct sockaddr_in))) { // // std::cout << "bind() failed" << std::endl; // // return -1; // // } // // // 设定目标连接地址(类似于asio的endpoint) // struct sockaddr_in targetEndpoint; // memset(&targetEndpoint, 0, sizeof(struct sockaddr_in)); // targetEndpoint.sin_family = AF_INET; // targetEndpoint.sin_port = htons(22); // targetEndpoint.sin_addr.s_addr = inet_addr("192.168.0.211"); // // 连接目标地址 // if (connect(socketfd, reinterpret_cast(&targetEndpoint), sizeof(struct sockaddr_in))) { // std::cout << "connect() failed" << std::endl; // return -1; // } // // // 使用ssh协议连接到远程主机 // LIBSSH2_SESSION* session = libssh2_session_init_ex(NULL, NULL, NULL, NULL); // if (!session) { // std::cout << "libssh2 session initialization failed" << std::endl; // return -1; // } // // int rc{0}; // // // 在debug模式下,输出调试日志 // libssh2_trace(session, ~0); // // if (rc = libssh2_session_handshake(session, socketfd)) { // std::cout << "libssh2_session_handshake() failed: " << rc << std::endl; // return -1; // } // // rc = 1; // // /* At this point we have not yet authenticated. The first thing to do // * is check the hostkey's fingerprint against our known hosts Your app // * may have it hard coded, may go to a file, may present it to the // * user, that's your call // */ // const char *fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); // fprintf(stderr, "Fingerprint: "); // for(int i = 0; i < 20; i++) { // fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]); // } // fprintf(stderr, "\n"); // // const char* username = "root"; // const char* password = "!QAZ2wsx!QAZ"; // // /* check what authentication methods are available */ // // userauthlist: publickey,password // char* userauthlist = libssh2_userauth_list(session, username, // (unsigned int)strlen(username)); // std::cout << "userauthlist: " << userauthlist << std::endl; // // // 如果不包含密码验证模式 // if (!strstr(userauthlist, "password")) { // std::cout << "不包含密码验证模式" << std::endl; // return -1; // } // // // 帐号和密码验证 // rc = libssh2_userauth_password(session, username, password); // if (rc != 0) { // std::cout << "用户名密码验证失败。。" << std::endl; // } // // std::cout << "成功" << std::endl; // // /* Request a session channel on which to run a shell */ // LIBSSH2_CHANNEL *channel = libssh2_channel_open_session(session); // if(!channel) { // fprintf(stderr, "Unable to open a session\n"); // return -1; // } // // // 设置会话的阻塞与非阻塞模式 // libssh2_session_set_blocking(session, 1); // // if(libssh2_channel_request_pty(channel, "vanilla")) { // fprintf(stderr, "Failed requesting pty\n"); // } // // // if(libssh2_channel_exec(channel, "uname -r\n ls -la\n pwd\n date")) { // // fprintf(stderr, "Unable to request command on channel\n"); // // return -1; // // } // // if(libssh2_channel_shell(channel)) { // fprintf(stderr, "Unable to request shell on allocated pty\n"); // return -1; // } // // char b[1024*8]; // libssh2_channel_read(channel, b, sizeof(b)); // // std::cout << "cmd: " << b << std::endl; // // const char* cmd = "ls"; // libssh2_channel_write(channel, cmd, sizeof(cmd)); // // // libssh2_channel_read(channel, b, sizeof(b)); // // std::cout << "cmd: " << b << std::endl; // // // while(!libssh2_channel_eof(channel)) { // // char buf[1024]; // // ssize_t err = libssh2_channel_read(channel, buf, sizeof(buf)); // // if(err < 0) // // fprintf(stderr, "Unable to read response: %ld\n", (long)err); // // else { // // fwrite(buf, 1, (size_t)err, stdout); // // } // // } // // // rc = libssh2_channel_get_exit_status(channel); // // if(libssh2_channel_close(channel)) // fprintf(stderr, "Unable to close channel\n"); // // if(channel) { // libssh2_channel_free(channel); // channel = NULL; // } // // if(session) { // libssh2_session_disconnect(session, "Normal Shutdown"); // libssh2_session_free(session); // } // // if(socketfd != LIBSSH2_INVALID_SOCKET) { // shutdown(socketfd, 2); // LIBSSH2_SOCKET_CLOSE(socketfd); // } // // // // 在使用完libssh2库后,清理分配的资源 // libssh2_exit(); // GoInt s = Add(10, 20); // std::cout << s << std::endl; // char buffer[512]; // int rs; // int sock; // std::cout << sizeof(int) << std::endl; // struct sockaddr_in addr; // struct pollfd pfd[2]; // struct addrinfo *ai; // struct addrinfo hints; // struct termios tios; // const char *servname; // const char *hostname; /* check usage */ // if (argc < 2) { // fprintf(stderr, "Usage:\n ./telnet-client [port]\n"); // return 1; // } /* process arguments */ // servname = (argc < 3) ? "23" : argv[2]; // hostname = argv[1]; // servname = "23"; // hostname = "127.0.0.1"; // // /* look up server host */ // memset(&hints, 0, sizeof(hints)); // hints.ai_family = AF_UNSPEC; // hints.ai_socktype = SOCK_STREAM; // if ((rs = getaddrinfo(hostname, servname, &hints, &ai)) != 0) { // fprintf(stderr, "getaddrinfo() failed for %s: %s\n", hostname, // gai_strerror(rs)); // return 1; // } // std::async(std::launch::async, [&]() { // servname = "23"; // hostname = "127.0.0.1"; // // /* look up server host */ // memset(&hints, 0, sizeof(hints)); // hints.ai_family = AF_UNSPEC; // hints.ai_socktype = SOCK_STREAM; // if ((rs = getaddrinfo(hostname, servname, &hints, &ai)) != 0) { // fprintf(stderr, "getaddrinfo() failed for %s: %s\n", hostname, // gai_strerror(rs)); // return 1; // } // // /* create server socket */ // if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { // fprintf(stderr, "socket() failed: %s\n", strerror(errno)); // return 1; // } // // // memset(&addr, 0, sizeof(addr)); // // addr.sin_family = AF_INET; // // if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { // // fprintf(stderr, "bind() failed: %s\n", strerror(errno)); // // close(sock); // // return 1; // // } // // if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { // fprintf(stderr, "connect() failed: %s\n", strerror(errno)); // close(sock); // return 1; // } // }); /* create server socket */ // if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { // fprintf(stderr, "socket() failed: %s\n", strerror(errno)); // return 1; // } /* bind server socket */ // memset(&addr, 0, sizeof(addr)); // addr.sin_family = AF_INET; // if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { // fprintf(stderr, "bind() failed: %s\n", strerror(errno)); // close(sock); // return 1; // } /* connect */ // if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { // fprintf(stderr, "connect() failed: %s\n", strerror(errno)); // close(sock); // return 1; // } // /* free address lookup info */ // freeaddrinfo(ai); // // /* set input echoing on by default */ // do_echo = 1; // // /* initialize telnet box */ // // telnet_t 包含了一个telnet连接当前的所有状态 // // telnet_init 必须要在tcp连接建立后,任何telent api 调用之前使用 // telnet = telnet_init(telopts, _event_handler, 0, &sock); // // memset(telnet_cache, 0x00, sizeof(telnet_cache)); // // while(1) // { // // 发送给服务端的字节缓存 // memset(buffer, 0x00, sizeof(buffer)); // // if((rs = recv(sock, buffer, sizeof(buffer), 0)) > 0) // { // // 将通过socket中接收到的数据交给libtelnet,由libtelnet根据接收到的信息,相机处理 // telnet_recv(telnet, buffer, rs); // // // 将接收到的数据解析完后,判断出服务器的意图,标记成do_some_step,接下来根据意图作相应的处理 // // // do_some_step == 1 表示收到login提示 // if(do_some_step == 1) // { // memset(buffer, 0x00, sizeof(buffer)); // // // twetec-All-Series login: twetec // strcpy(buffer, "twetec"); // // strcat(buffer, "\r\n"); // // rs = strlen(buffer); // // _input(buffer, rs); // // memset(buffer, 0x00, sizeof(buffer)); // // do_some_step = 2; // } // // 密码提示符。输入密码 // else if(do_some_step == 3) // { // memset(buffer, 0x00, sizeof(buffer)); // // strcpy(buffer, "Twe201616"); // // strcat(buffer, "\r\n"); // // rs = strlen(buffer); // // _input(buffer, rs); // // memset(buffer, 0x00, sizeof(buffer)); // // strcpy(buffer, "echo "TELNET_BEGIN_STRING); // // strcat(buffer, "\r\n"); // // rs = strlen(buffer); // // _input(buffer, rs); // // memset(buffer, 0x00, sizeof(buffer)); // // do_some_step = 4; // } // // 命令提示符,执行3条指令 // else if(do_some_step == 5) // { // memset(buffer, 0x00, sizeof(buffer)); // // strcpy(buffer, "cd priv/test"); // // strcat(buffer, "\r\n"); // // rs = strlen(buffer); // // _input(buffer, rs); // // memset(buffer, 0x00, sizeof(buffer)); // // strcpy(buffer, "echo "TELNET_LS_BEGIN_STRING""); // // strcat(buffer, "\r\n"); // // rs = strlen(buffer); // // _input(buffer, rs); // // memset(buffer, 0x00, sizeof(buffer)); // // strcpy(buffer, "ls -lrt"); // // strcat(buffer, "\r\n"); // // rs = strlen(buffer); // // _input(buffer, rs); // // strcpy(buffer, "echo \""TELNET_LS_END_STRING"\""); // // strcat(buffer, "\r\n"); // // rs = strlen(buffer); // // _input(buffer, rs); // // memset(buffer, 0x00, sizeof(buffer)); // // do_some_step = 6; // } // else if(do_some_step == 8) // { // memset(buffer, 0x00, sizeof(buffer)); // // strcpy(buffer, "exit"); // // strcat(buffer, "\r\n"); // // rs = strlen(buffer); // // _input(buffer, rs); // // // break; // } // else // { // memset(buffer, 0x00, sizeof(buffer)); // } // } // } // // /* clean up */ // telnet_free(telnet); // close(sock); // // 初始化libssh2库,在应用程序启动时,只调用一次 // int rc = libssh2_init(0); // if (rc != 0) { // std::cout << "libssh2 initialization failed" << std::endl; // } // // // 创建socket(套接字) // int socketfd = socket(AF_INET, SOCK_STREAM, 0); // if (socketfd < 0) { // std::cout << "socket() failed" << std::endl; // return -1; // } // // // 设定本地网卡地址 // struct sockaddr_in localEndpoint; // memset(&localEndpoint, 0, sizeof(struct sockaddr_in)); // localEndpoint.sin_family = AF_INET; // localEndpoint.sin_addr.s_addr = inet_addr("192.168.0.110"); // localEndpoint.sin_port = 0; // // 绑定本地网卡 // if (bind(socketfd, reinterpret_cast(&localEndpoint), sizeof(struct sockaddr_in))) { // std::cout << "bind() failed" << std::endl; // return -1; // } // // // 设定目标连接地址(类似于asio的endpoint) // struct sockaddr_in targetEndpoint; // memset(&targetEndpoint, 0, sizeof(struct sockaddr_in)); // targetEndpoint.sin_family = AF_INET; // targetEndpoint.sin_port = htons(22); // targetEndpoint.sin_addr.s_addr = inet_addr("192.168.0.151"); // // 连接目标地址 // if (connect(socketfd, reinterpret_cast(&targetEndpoint), sizeof(struct sockaddr_in))) { // std::cout << "connect() failed" << std::endl; // return -1; // } // // // 使用ssh协议连接到远程主机 // LIBSSH2_SESSION* session = libssh2_session_init(); // if (!session) { // std::cout << "libssh2 session initialization failed" << std::endl; // return -1; // } // // // libssh2_session_method_pref(session, LIBSSH2_METHOD_KEX, "diffie-hellman-group14-sha1"); // // libssh2_session_method_pref(session, LIBSSH2_METHOD_CRYPT_CS, "aes256-ctr"); // // libssh2_session_method_pref(session, LIBSSH2_METHOD_CRYPT_SC, "aes256-ctr"); // // libssh2_session_method_pref(session, LIBSSH2_METHOD_MAC_CS, "hmac-sha1"); // // libssh2_session_method_pref(session, LIBSSH2_METHOD_MAC_SC, "hmac-sha1"); // // // libssh2_session_method_pref(session, LIBSSH2_METHOD_COMP, "none"); // // libssh2_session_method_pref(session, LIBSSH2_METHOD_LANG_CS, ""); // // libssh2_session_method_pref(session, LIBSSH2_METHOD_LANG_SC, ""); // // // 在debug模式下,输出调试日志 // libssh2_trace(session, LIBSSH2_TRACE_CONN); // // if (rc = libssh2_session_handshake(session, socketfd)) { // std::cout << "libssh2_session_handshake() failed: " << rc << std::endl; // return -1; // } // // rc = 1; // // /* At this point we have not yet authenticated. The first thing to do // * is check the hostkey's fingerprint against our known hosts Your app // * may have it hard coded, may go to a file, may present it to the // * user, that's your call // */ // const char *fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); // fprintf(stderr, "Fingerprint: "); // for(int i = 0; i < 20; i++) { // fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]); // } // fprintf(stderr, "\n"); // // const char* username = "ubuntu"; // const char* password = "!QAZ2wsx@123"; // // /* check what authentication methods are available */ // // userauthlist: publickey,password // char* userauthlist = libssh2_userauth_list(session, username, // (unsigned int)strlen(username)); // std::cout << "userauthlist: " << userauthlist << std::endl; // // // 如果不包含密码验证模式 // if (!strstr(userauthlist, "password")) { // std::cout << "不包含密码验证模式" << std::endl; // return -1; // } // // // 帐号和密码验证 // rc = libssh2_userauth_password(session, username, password); // if (rc != 0) { // std::cout << "用户名密码验证失败。。" << std::endl; // } // // std::cout << "成功" << std::endl; // // /* Request a session channel on which to run a shell */ // LIBSSH2_CHANNEL *channel = libssh2_channel_open_session(session); // if(!channel) { // fprintf(stderr, "Unable to open a session\n"); // return -1; // } // // // 设置会话的阻塞与非阻塞模式 // libssh2_session_set_blocking(session, 1); // // if(libssh2_channel_request_pty(channel, "vanilla")) { // fprintf(stderr, "Failed requesting pty\n"); // } // // // if(libssh2_channel_exec(channel, "uname -r\n ls -la\n pwd\n date")) { // // fprintf(stderr, "Unable to request command on channel\n"); // // return -1; // // } // // if(libssh2_channel_shell(channel)) { // fprintf(stderr, "Unable to request shell on allocated pty\n"); // return -1; // } // // char b[1024*8]; // libssh2_channel_read(channel, b, sizeof(b)); // // std::cout << "cmd: " << b << std::endl; // // const char* cmd = "ls"; // libssh2_channel_write(channel, cmd, sizeof(cmd)); // // // libssh2_channel_read(channel, b, sizeof(b)); // // std::cout << "cmd: " << b << std::endl; // // // while(!libssh2_channel_eof(channel)) { // // char buf[1024]; // // ssize_t err = libssh2_channel_read(channel, buf, sizeof(buf)); // // if(err < 0) // // fprintf(stderr, "Unable to read response: %ld\n", (long)err); // // else { // // fwrite(buf, 1, (size_t)err, stdout); // // } // // } // // // rc = libssh2_channel_get_exit_status(channel); // // if(libssh2_channel_close(channel)) // fprintf(stderr, "Unable to close channel\n"); // // if(channel) { // libssh2_channel_free(channel); // channel = NULL; // } // // if(session) { // libssh2_session_disconnect(session, "Normal Shutdown"); // libssh2_session_free(session); // } // // if(socketfd != LIBSSH2_INVALID_SOCKET) { // shutdown(socketfd, 2); // LIBSSH2_SOCKET_CLOSE(socketfd); // } // // // // 在使用完libssh2库后,清理分配的资源 // libssh2_exit(); while (std::getchar() != '\n'); /** * 声明telnet支持的配置项 */ static const telnet_telopt_t telopts[] = { { TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DO }, { TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DONT }, { TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO }, { TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DO }, { -1, 0, 0 } }; static void _cleanup(void) { tcsetattr(STDOUT_FILENO, TCSADRAIN, &orig_tios); } /** * 通过libtelnet发送字串 */ static void _input(char *buffer, int size) { static char crlf[] = { '\r', '\n' }; int i; for (i = 0; i != size; ++i) { /* if we got a CR or LF, replace with CRLF * NOTE that usually you'd get a CR in UNIX, but in raw * mode we get LF instead (not sure why) */ if (buffer[i] == '\r' || buffer[i] == '\n') { if (do_echo) printf("\r\n"); // 向服务端发送二进制数据 telnet_send(telnet, crlf, 2); } else { if (do_echo) putchar(buffer[i]); // 向服务端发送二进制数据 telnet_send(telnet, buffer + i, 1); } } fflush(stdout); } /** * 向socket发送数据 */ static void _send(int sock, const char *buffer, size_t size) { int rs; /* send data */ while (size > 0) { if ((rs = send(sock, buffer, size, 0)) == -1) { fprintf(stderr, "send() failed: %s\n", strerror(errno)); exit(1); } else if (rs == 0) { fprintf(stderr, "send() unexpectedly returned 0\n"); exit(1); } /* update pointer and size to see if we've got more to send */ buffer += rs; size -= rs; } } #include #include #include #include #include static void _event_handler(telnet_t *telnet, telnet_event_t *ev, void *user_data) { int sock = *(int*)user_data; int rs = 0; int deal_len = 0; char deal_flag = 0; char deal_type = 0; char show_flag = 0; const char *p = telnet_cache; const char *q = telnet_cache; switch (ev->type) { /* data received */ case TELNET_EV_DATA: // 如果有接收到数据,则将数据缓存在telnet_cache字符数组中 if(ev->data.size > 0) { int data_size = ev->data.size; // 起始地址 memcpy(telnet_cache+telnet_cache_len, ev->data.buffer, data_size); telnet_cache_len += data_size; telnet_cache[telnet_cache_len] = 0x00; rs = telnet_cache_len; } printf("telnet_cache_len current = %d\n", telnet_cache_len); printf("telnet_cache current = %s\n", telnet_cache); // 将服务端返回的指令,用\r\n分割 q = strstr(p, "\r\n"); deal_type = 0; show_flag = 1; // q == NULL 很关键 if(do_some_step == 0) { // q == NULL 表示 p指向的指令已经是最后一条指令了 if(q == NULL) { q = strstr(p, "login: "); deal_type = 1; } } else if(do_some_step == 2) { if(q == NULL) { q = strstr(p, "Password: "); deal_type = 2; } } else if(do_some_step == 4 || do_some_step == 6) { if(q == NULL) { q = strstr(p, ":~$"); deal_type = 3; show_flag = 0; } if(q == NULL) { q = strstr(p, ":~/priv/test$"); deal_type = 4; show_flag = 0; } } // if(1) // { // printf("telnet_cache_len current = %d\n", telnet_cache_len); // printf("telnet_cache current = %s\n", telnet_cache); // } // 查看后半部分是否还有指令 (q 是通过\r\n分割的后半部分) while(q != NULL) { char buffer[1024]; // 存储服务端响应内容的前半部分 deal_flag = 1; memset(buffer, 0x00, sizeof(buffer)); if(deal_type == 0) { memcpy(buffer, p, q-p); // 把\r\n分割的前半部分存入buffer buffer[q-p] = 0x00; // 结尾加上结束标志 deal_len += (q-p) + 2; // } else if(deal_type == 1) { memcpy(buffer, p, q-p+7); buffer[q-p+7] = 0x00; deal_len += (q-p+7); } else if(deal_type == 2) { memcpy(buffer, p, q-p+10); buffer[q-p+10] = 0x00; deal_len += (q-p+10); } else if(deal_type == 3) { memcpy(buffer, p, q-p+4); buffer[q-p+4] = 0x00; deal_len += (q-p+4); show_flag = 0; } else if(deal_type == 4) { memcpy(buffer, p, q-p+14); buffer[q-p+14] = 0x00; deal_len += (q-p+14); show_flag = 0; } else { memcpy(buffer, p, q-p); buffer[q-p] = 0x00; deal_len += (q-p) + 2; } //printf("deal_type = %d, buffer = %s, q = %s\n", deal_type, buffer, q); /*if(do_some_step == 4) { printf("p = %d\n", p); printf("q = %d\n", q); printf("q-p+2 = %d\n", q-p+2); printf("deal_len after = %d\n", deal_len); }*/ // 查看前半部分是否有要处理的指令(服务端传回来的可能是多条指令,用\r\n分割) if(strstr(buffer, "login:") != NULL) { if(do_some_step == 0) { do_some_step = 1; } } else if(strstr(buffer, "Password:") != NULL) { if(do_some_step == 2) { do_some_step = 3; } } else if(strstr(buffer, TELNET_BEGIN_STRING) != NULL) { if(do_some_step == 4) { if(strncmp(buffer, "echo", 4) != 0) { //printf("buffer = %s\n", buffer); do_some_step = 5; } } } else if(strstr(buffer, TELNET_LS_BEGIN_STRING) != NULL) { if(do_some_step == 6) { if(strncmp(buffer, "echo", 4) != 0) { show_flag = 0; //printf("buffer = %s\n", buffer); do_some_step = 7; } } } else if(strstr(buffer, TELNET_LS_END_STRING) != NULL) { if(do_some_step == 7) { if(strncmp(buffer, "echo", 4) != 0) { //printf("buffer = %s\n", buffer); do_some_step = 8; } } } if(do_some_step == 7) { if(show_flag == 1) { if(strstr(buffer, ":~$") == NULL && strstr(buffer, ":~/priv/test$") == NULL && strstr(buffer, TELNET_LS_BEGIN_STRING) == NULL) { printf("%s\n", buffer); } else if(strstr(buffer, "ls -") != NULL) { char *p = strstr(buffer, "ls -"); printf("$ %s\n", p); } } } if(deal_type == 0) { p = q + 2; // /r/n 将p移到下一条指令的起始位置 } else if(deal_type == 1) { p = q + 7; // login: } else if(deal_type == 2) { p = q + 10; // Password: } else if(deal_type == 3) { p = q + 4; } else if(deal_type == 4) { p = q + 14; } else { p = q + 2; } show_flag = 1; q = strstr(p, "\r\n"); deal_type = 0; if(do_some_step == 0) { if(q == NULL) { q = strstr(p, "login: "); deal_type = 1; } } else if(do_some_step == 2) { if(q == NULL) { q = strstr(p, "Password: "); deal_type = 2; } } else if(do_some_step == 4 || do_some_step == 6) { if(q == NULL) { q = strstr(p, ":~$"); deal_type = 3; if(q != NULL) { show_flag = 0; } } if(q == NULL) { q = strstr(p, ":~/priv/test$"); deal_type = 4; if(q != NULL) { show_flag = 0; } } } } if(deal_len > 0) { int i = 0; // 剩余未处理的字符串长度 = 接收到的字符串长度 - 已处理的字符串长度 int p_len = telnet_cache_len - deal_len; for(i=0; idata.buffer, ev->data.size); break; /* request to enable remote feature (or receipt) */ case TELNET_EV_WILL: /* we'll agree to turn off our echo if server wants us to stop */ if (ev->neg.telopt == TELNET_TELOPT_ECHO) do_echo = 0; break; /* notification of disabling remote feature (or receipt) */ case TELNET_EV_WONT: if (ev->neg.telopt == TELNET_TELOPT_ECHO) do_echo = 1; break; /* request to enable local feature (or receipt) */ case TELNET_EV_DO: break; /* demand to disable local feature (or receipt) */ case TELNET_EV_DONT: break; /* respond to TTYPE commands */ case TELNET_EV_TTYPE: /* respond with our terminal type, if requested */ if (ev->ttype.cmd == TELNET_TTYPE_SEND) { telnet_ttype_is(telnet, getenv("TERM")); } break; /* respond to particular subnegotiations */ case TELNET_EV_SUBNEGOTIATION: break; /* error */ case TELNET_EV_ERROR: printf("event TELNET_EV_ERROR\n"); exit(1); default: /* ignore */ break; } } #ifdef HAVE_ZLIB #include "zlib.h" #endif #define TELNET_BEGIN_STRING "===*****welcome to use telnet*****===" #define TELNET_END_STRING "===*****goodbye to use telnet*****===" #define TELNET_LS_BEGIN_STRING "=^**#####ls begin#####**^=" #define TELNET_LS_END_STRING "=^**#####ls end#####**^=" static struct termios orig_tios; static telnet_t *telnet; static int do_echo; static int do_some_step = 0; static char telnet_cache[2048]; static int telnet_cache_len = 0; #include #include #include // PQsocket() // std::ignore = std::async(std::launch::async, []() { // // 获取libPQ的版本 // std::uint32_t libPQVersion = PQlibVersion(); // std::cout << "libVersion: " << libPQVersion << std::endl; // // const char* paramKeys[] = { // "host", // 要连接的主机的数字 IP 地址。 这应该是标准 IPv4 地址格式,例如 172.28.40.9。 如果您的机器支持 IPv6,您也可以使用这些地址 // "port", // 服务器主机上连接的端口号 // "dbname", // 数据库名称 // "user", // 要连接的 PostgreSQL 用户名 // "password", // 服务器要求密码验证时使用的密码 // "localaddr", // "connect_timeout" // 连接时等待的最长时间,以秒为单位(写为十进制整数,例如 10)。 零、负数或未指定意味着无限期等待。 允许的最小超时为 2 秒,因此值 1 被解释为 2 // }; // // const char* paramValues[] = { // "192.168.0.102", // "5432", // "ganzhi", // "postgres", // "root", // "192.168.0.108", // "13" // }; // // // 连接PQ数据库服务器 // PGconn* connPtr = PQconnectdbParams(paramKeys, paramValues, 0); // // // 检查连接是否成功 // ConnStatusType status = PQstatus(connPtr); // // // 如果连接状态不是成功 // if (status != CONNECTION_OK) { // // 错误信息 // SPDLOG_INFO("PgSQL观测目标连接失败:{}", PQerrorMessage(connPtr)); // // 关闭与服务器的而连接,同时释放了PGconn对象的内存 注:即使服务器连接失败,也要调用finish函数,回收内存 // PQfinish(connPtr); // // 结束执行 // // return; // } // // // 让服务器执行SQL语句 // PGresult* execResult = PQexec(connPtr, "SELECT 1"); // // // 检查查询是否成功 // ExecStatusType execStatus = PQresultStatus(execResult); // // // 如果查询语句执行失败 // if (execStatus != PGRES_TUPLES_OK) { // // 错误信息 // SPDLOG_INFO("PgSQL观测目标查询失败:{}", PQerrorMessage(connPtr)); // // 释放PGresult查询结果,有PGresult对象,就必须释放 // PQclear(execResult); // // 关闭与服务器的而连接,同时释放了PGconn对象的内存 注:即使服务器连接失败,也要调用finish函数,回收内存 // PQfinish(connPtr); // // 结束执行 // // return; // } // // // 释放PGresult查询结果,有PGresult对象,就必须释放 // PQclear(execResult); // // 关闭与服务器的而连接,同时释放了PGconn对象的内存 注:即使服务器连接失败,也要调用finish函数,回收内存 // PQfinish(connPtr); // }); // // while (getchar() != '\n'); std::future future = std::async(std::launch::async, []() { // 获取libPQ的版本 std::uint32_t libPQVersion = PQlibVersion(); std::cout << "libVersion: " << libPQVersion << std::endl; const char* paramKeys[] = { "host", // 要连接的主机的数字 IP 地址。 这应该是标准 IPv4 地址格式,例如 172.28.40.9。 如果您的机器支持 IPv6,您也可以使用这些地址 "port", // 服务器主机上连接的端口号 "dbname", // 数据库名称 "user", // 要连接的 PostgreSQL 用户名 "password", // 服务器要求密码验证时使用的密码 "connect_timeout", // 连接时等待的最长时间,以秒为单位(写为十进制整数,例如 10)。 零、负数或未指定意味着无限期等待。 允许的最小超时为 2 秒,因此值 1 被解释为 2 NULL }; const char* paramValues[] = { "192.168.0.102", "5432", "ganzhi", "postgres", "root", "13", NULL }; // 连接PQ数据库服务器 PGconn* connPtr = PQconnectdbParams(paramKeys, paramValues, 0); // 检查连接是否成功 ConnStatusType status = PQstatus(connPtr); // 如果连接状态不是成功 if (status != CONNECTION_OK) { // 错误信息 SPDLOG_INFO("PgSQL观测目标连接失败:{}", PQerrorMessage(connPtr)); // 关闭与服务器的而连接,同时释放了PGconn对象的内存 注:即使服务器连接失败,也要调用finish函数,回收内存 PQfinish(connPtr); // 结束执行 // return; } // 让服务器执行SQL语句 PGresult* execResult = PQexec(connPtr, "SELECT 1"); // 检查查询是否成功 ExecStatusType execStatus = PQresultStatus(execResult); // 如果查询语句执行失败 if (execStatus != PGRES_TUPLES_OK) { // 错误信息 SPDLOG_INFO("PgSQL观测目标查询失败:{}", PQerrorMessage(connPtr)); // 释放PGresult查询结果,有PGresult对象,就必须释放 PQclear(execResult); // 关闭与服务器的而连接,同时释放了PGconn对象的内存 注:即使服务器连接失败,也要调用finish函数,回收内存 PQfinish(connPtr); // 结束执行 return; } // 释放PGresult查询结果,有PGresult对象,就必须释放 PQclear(execResult); // 关闭与服务器的而连接,同时释放了PGconn对象的内存 注:即使服务器连接失败,也要调用finish函数,回收内存 PQfinish(connPtr); }); while (getchar() != '\n'); // 创建socket(套接字) int socketfd = socket(AF_INET, SOCK_STREAM, 0); if (socketfd < 0) { std::cout << "socket() failed" << std::endl; return -1; } // 设定本地网卡地址 struct sockaddr_in localEndpoint; memset(&localEndpoint, 0, sizeof(struct sockaddr_in)); localEndpoint.sin_family = AF_INET; localEndpoint.sin_addr.s_addr = inet_addr("192.168.0.110"); localEndpoint.sin_port = 0; // 绑定本地网卡 if (bind(socketfd, reinterpret_cast(&localEndpoint), sizeof(struct sockaddr_in))) { std::cout << "bind() failed" << std::endl; return -1; } // 设定目标连接地址(类似于asio的endpoint) struct sockaddr_in targetEndpoint; memset(&targetEndpoint, 0, sizeof(struct sockaddr_in)); targetEndpoint.sin_family = AF_INET; targetEndpoint.sin_port = htons(22); targetEndpoint.sin_addr.s_addr = inet_addr("192.168.0.211"); // 连接目标地址 if (connect(socketfd, reinterpret_cast(&targetEndpoint), sizeof(struct sockaddr_in))) { std::cout << "connect() failed" << std::endl; return -1; } // 创建SSH会话 LIBSSH2_SESSION* session = libssh2_session_init(); if (!session) { std::cout << "libssh2 session initialization failed" << std::endl; return -1; } int rc{0}; // 在debug模式下,输出调试日志 // libssh2_trace(session, ~0); // 设置会话的阻塞与非阻塞模式 libssh2_session_set_blocking(session, 0); // 启动SSH会话 while ((rc = libssh2_session_handshake(session, socketfd)) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } if (rc != 0) { std::cout << "libssh2_session_handshake() failed: " << rc << std::endl; return -1; } // rc = 1; /* At this point we have not yet authenticated. The first thing to do * is check the hostkey's fingerprint against our known hosts Your app * may have it hard coded, may go to a file, may present it to the * user, that's your call */ // const char *fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); // fprintf(stderr, "Fingerprint: "); // for(int i = 0; i < 20; i++) { // fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]); // } // fprintf(stderr, "\n"); const char* username = "root"; const char* password = "!QAZ2wsx!QAZ"; /* check what authentication methods are available */ // userauthlist: publickey,password // char* userauthlist = libssh2_userauth_list(session, username, // (unsigned int)strlen(username)); // std::cout << "userauthlist: " << userauthlist << std::endl; // 如果不包含密码验证模式 // if (!strstr(userauthlist, "password")) { // std::cout << "不包含密码验证模式" << std::endl; // return -1; // } // 帐号和密码验证 while ((rc = libssh2_userauth_password(session, username, password)) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } // rc = libssh2_userauth_password(session, username, password); if (rc != 0) { std::cout << "用户名密码验证失败。。" << std::endl; } std::cout << "成功" << std::endl; // 打开通道 // LIBSSH2_CHANNEL *channel = libssh2_channel_open_session(session); LIBSSH2_CHANNEL* channel = nullptr; while ((channel = libssh2_channel_open_session(session)) == NULL && libssh2_session_last_error(session, NULL, NULL, 0) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } if(!channel) { fprintf(stderr, "Unable to open a session\n"); return -1; } char modes[] = { 1, 0, 53, 1, 0 }; rc = 0; while ((rc = libssh2_channel_request_pty(channel, "xterm")) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } if (rc != 0) { fprintf(stderr, "Error\n"); exit(1); } // while (rc = libssh2_channel_setenv(channel, ) == LIBSSH2_ERROR_EAGAIN) // { // waitsocket(socketfd, session); // } // if (rc != 0) // { // fprintf(stderr, "Error\n"); // exit(1); // } // if(libssh2_channel_request_pty(channel, "xterm")) { // fprintf(stderr, "Failed requesting pty\n"); // } // // libssh2_channel_request_pty_size(channel, 10000, 100000); while ((rc = libssh2_channel_shell(channel)) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } if (rc != 0) { fprintf(stderr, "Error\n"); exit(1); } // while ((rc = libssh2_channel_write(channel, "stty echo\n", strlen("stty echo\n"))) == LIBSSH2_ERROR_EAGAIN) // { // waitsocket(socketfd, session); // } // // if (rc < 0) // { // fprintf(stderr, "Error\n"); // exit(1); // } while ((rc = libssh2_channel_write(channel, "system-view\ndisplay current-configuration\n", strlen("system-view\ndisplay current-configuration\n"))) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } if (rc < 0) { fprintf(stderr, "Error\n"); exit(1); } // 执行远程命令 // if(libssh2_channel_exec(channel, "PAGER=cat\nsystem-view\ndisplay current-configuration\n ")) { // fprintf(stderr, "Unable to request command on channel\n"); // return -1; // } // std::this_thread::sleep_for(std::chrono::seconds(3)); // if(libssh2_channel_shell(channel)) { // fprintf(stderr, "Unable to request shell on allocated pty\n"); // return -1; // } // // char b[1024*8]; // libssh2_channel_read(channel, b, sizeof(b)); // // std::cout << "cmd: " << b << std::endl; // // const char* cmd = "ls"; // libssh2_channel_write(channel, cmd, sizeof(cmd)); // // // libssh2_channel_read(channel, b, sizeof(b)); // // std::cout << "cmd: " << b << std::endl; // while ((rc = libssh2_channel_send_eof(channel)) == LIBSSH2_ERROR_EAGAIN) // { // waitsocket(socketfd, session); // } // if (rc < 0) // { // fprintf(stderr, "Error\n"); // exit(1); // } int bytecount = 0; constexpr std::size_t BACKUP_DATA_SIZE = 50 * 1024; // 备份数据区尺寸 char backupData[BACKUP_DATA_SIZE]; // 备份数据区 memset(backupData, 0, BACKUP_DATA_SIZE); // 重置备份数据区 char* backupDataPtr{backupData}; // 备份数据区指针 std::size_t readRetryCount{0}; // 读取重试次数 while (true) { // 判断重试次数是否超限(重试3次),如果超限则停止读取,表示备份完毕 if (readRetryCount >= 3) { libssh2_channel_close(channel); libssh2_channel_free(channel); libssh2_session_disconnect(session, "Normal Shutdown"); libssh2_session_free(session); LIBSSH2_SOCKET_CLOSE(socketfd); std::cout << "备份失败..." << std::endl; break; } // 通道读取缓存 constexpr std::size_t CHANNEL_BUFFER_SIZE = 1024 * 10; // 通道缓存区字节大小 char channelBuffer[CHANNEL_BUFFER_SIZE]; // 通道缓存区 memset(channelBuffer, 0, CHANNEL_BUFFER_SIZE); // 重置通道缓存区 // 已读到的字节数 std::int32_t readBytesCount{0}; do { // fprintf(stderr, "BackupData:\n"); // for (std::size_t i = 0; i < 10240; ++i) // fputc(backupData[i], stderr); // fprintf(stderr, "\n"); // 处理完数据后,重置缓存 memset(channelBuffer, 0, CHANNEL_BUFFER_SIZE); // 尝试读取数据 readBytesCount = libssh2_channel_read(channel, channelBuffer, CHANNEL_BUFFER_SIZE); // 如果读取到了数据,则进行处理 if (readBytesCount > 0) { // 读到数据后,重置重试次数 readRetryCount = 0; // 查看返回的字符串中,是否含有 More 符号 char* moreSymbolPtr = strstr(channelBuffer, "---- More ----"); // 如果存在more符号,则先过滤,再进行拷贝 if (moreSymbolPtr != NULL) { // backupDataPtr永远指向下一个空的区域 memcpy(backupDataPtr, channelBuffer, moreSymbolPtr - channelBuffer); // 移动备份数据指针到下一个空白区 backupDataPtr += (moreSymbolPtr - channelBuffer); // 如果包含了more符号,则继续向服务端发送换行符,继续读取 std::int32_t moreBytesCount{0}; while ((moreBytesCount = libssh2_channel_write(channel, " ", strlen(" "))) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } if (moreBytesCount < 0){ SPDLOG_INFO("向SSH服务端写入More指令失败.."); } // 继续下一次读取 continue; } // 将读到的数据,存储到备份数据中 memcpy(backupDataPtr, channelBuffer, readBytesCount); // 移动备份数据指针到下一个空白区 backupDataPtr += readBytesCount; } // 休息一会再读 // std::this_thread::sleep_for(std::chrono::milliseconds(50)); } while (readBytesCount > 0) ; // 如果这次读取到了数据,则继续下一次读取 // 如果这次尝试读取失败,看是否是服务端还未响应完,没响应完则等待 if (readBytesCount == LIBSSH2_ERROR_EAGAIN) { // 等待socket响应 waitsocket(socketfd, session); // 如果服务器确认响应完了,读取确认就是失败的了,则记录重试次数 readRetryCount ++; } } std::string s{backupData, static_cast(backupDataPtr-backupData)}; std::cout << s << std::endl; // 不断尝试读取服务端返回的内容 // while (true) // { // /* loop until we block */ // int rc{0}; // do // { // char buffer[0x4000]; // rc = libssh2_channel_read(channel, buffer, sizeof(buffer)); // // if (rc > 0) // { // int i; // bytecount += rc; // fprintf(stderr, "We read:\n"); // for (i = 0; i < rc; ++i) // fputc(buffer[i], stderr); // fprintf(stderr, "\n"); // // if (strstr(buffer, "---- More ----")) { // int m = 0; // while ((m = libssh2_channel_write(channel, "\n", strlen("\n"))) == LIBSSH2_ERROR_EAGAIN) // { // waitsocket(socketfd, session); // } // if (m < 0) // { // fprintf(stderr, "Error\n"); // exit(1); // } // } // } // else { // if (rc != LIBSSH2_ERROR_EAGAIN) // std::cout << "Hello World" << std::endl; // /* no need to output this for the EAGAIN case */ // fprintf(stderr, "libssh2_channel_read returned %d\n", rc); // } // // std::this_thread::sleep_for(std::chrono::milliseconds(50)); // } while (rc > 0); // // /* this is due to blocking that would occur otherwise so we loop on // this condition */ // if (rc == LIBSSH2_ERROR_EAGAIN) // { // waitsocket(socketfd, session); // } // else // break; // } // while(!libssh2_channel_eof(channel)) { // std::cout << "Hello World" << std::endl; // // char buf[1024]; // ssize_t err = libssh2_channel_read(channel, buf, sizeof(buf)); // if(err < 0) // fprintf(stderr, "Unable to read response: %ld\n", (long)err); // else { // fwrite(buf, 1, (size_t)err, stdout); // } // } // rc = libssh2_channel_get_exit_status(channel); if(libssh2_channel_close(channel)) fprintf(stderr, "Unable to close channel\n"); if(channel) { libssh2_channel_free(channel); channel = NULL; } if(session) { libssh2_session_disconnect(session, "Normal Shutdown"); libssh2_session_free(session); } if(socketfd != LIBSSH2_INVALID_SOCKET) { shutdown(socketfd, 2); LIBSSH2_SOCKET_CLOSE(socketfd); } // 在使用完libssh2库后,清理分配的资源 libssh2_exit(); #include #include #include #include static int waitsocket(int socket_fd, LIBSSH2_SESSION *session) { struct timeval timeout; int rc; fd_set fd; fd_set *writefd = NULL; fd_set *readfd = NULL; int dir; timeout.tv_sec = 10; timeout.tv_usec = 0; FD_ZERO(&fd); FD_SET(socket_fd, &fd); /* now make sure we wait in the correct direction */ dir = libssh2_session_block_directions(session); if (dir & LIBSSH2_SESSION_BLOCK_INBOUND) readfd = &fd; if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) writefd = &fd; rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout); return rc; } // 创建socket(套接字) int socketfd = socket(AF_INET, SOCK_STREAM, 0); if (socketfd < 0) { std::cout << "socket() failed" << std::endl; return -1; } // 设定本地网卡地址 struct sockaddr_in localEndpoint; memset(&localEndpoint, 0, sizeof(struct sockaddr_in)); localEndpoint.sin_family = AF_INET; localEndpoint.sin_addr.s_addr = inet_addr("192.168.0.110"); localEndpoint.sin_port = 0; // 绑定本地网卡 if (bind(socketfd, reinterpret_cast(&localEndpoint), sizeof(struct sockaddr_in))) { std::cout << "bind() failed" << std::endl; return -1; } // 设定目标连接地址(类似于asio的endpoint) struct sockaddr_in targetEndpoint; memset(&targetEndpoint, 0, sizeof(struct sockaddr_in)); targetEndpoint.sin_family = AF_INET; targetEndpoint.sin_port = htons(22); targetEndpoint.sin_addr.s_addr = inet_addr("192.168.0.211"); // 连接目标地址 if (connect(socketfd, reinterpret_cast(&targetEndpoint), sizeof(struct sockaddr_in))) { std::cout << "connect() failed" << std::endl; return -1; } // 创建SSH会话 LIBSSH2_SESSION* session = libssh2_session_init(); if (!session) { std::cout << "libssh2 session initialization failed" << std::endl; return -1; } int rc{0}; // 在debug模式下,输出调试日志 // libssh2_trace(session, ~0); // 设置会话的阻塞与非阻塞模式 libssh2_session_set_blocking(session, 0); // // 设置支持的算法(优先级从高到低) // const char *algorithms = // "diffie-hellman-group-exchange-sha256," // "ecdh-sha2-nistp256,ecdh-sha2-nistp384," // "diffie-hellman-group16-sha512," // "rsa-sha2-512,rsa-sha2-256"; // // if ((rc = libssh2_session_method_pref(session, LIBSSH2_METHOD_KEX, algorithms)) == LIBSSH2_ERROR_EAGAIN) { // waitsocket(socketfd, session); // } // if (rc != 0) { // std::cout << "libssh2_session_method_pref() failed: " << rc << std::endl; // return -1; // } // // // 设置其他方法(可选但推荐) // while ((rc = libssh2_session_method_pref(session, LIBSSH2_METHOD_CRYPT_CS, "aes256-ctr,aes192-ctr,aes128-ctr")) == LIBSSH2_ERROR_EAGAIN) { // waitsocket(socketfd, session); // } // if (rc != 0) { // std::cout << "libssh2_session_method_pref() failed: " << rc << std::endl; // return -1; // } // // // 设置其他方法(可选但推荐) // while ((rc = libssh2_session_method_pref(session, LIBSSH2_METHOD_MAC_CS, "hmac-sha2-256,hmac-sha1")) == LIBSSH2_ERROR_EAGAIN) { // waitsocket(socketfd, session); // } // if (rc != 0) { // std::cout << "libssh2_session_method_pref() failed: " << rc << std::endl; // return -1; // } // 启动SSH会话 while ((rc = libssh2_session_handshake(session, socketfd)) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } if (rc != 0) { char *errmsg; libssh2_session_last_error(session, &errmsg, NULL, 0); fprintf(stderr, "握手失败: %s (代码 %d)\n", errmsg, rc); exit(1); } // rc = 1; /* At this point we have not yet authenticated. The first thing to do * is check the hostkey's fingerprint against our known hosts Your app * may have it hard coded, may go to a file, may present it to the * user, that's your call */ // const char *fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); // fprintf(stderr, "Fingerprint: "); // for(int i = 0; i < 20; i++) { // fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]); // } // fprintf(stderr, "\n"); const char* username = "root"; const char* password = "!QAZ2wsx!QAZ"; /* check what authentication methods are available */ // userauthlist: publickey,password // char* userauthlist = libssh2_userauth_list(session, username, // (unsigned int)strlen(username)); // std::cout << "userauthlist: " << userauthlist << std::endl; // 如果不包含密码验证模式 // if (!strstr(userauthlist, "password")) { // std::cout << "不包含密码验证模式" << std::endl; // return -1; // } // 帐号和密码验证 while ((rc = libssh2_userauth_password(session, username, password)) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } // rc = libssh2_userauth_password(session, username, password); if (rc != 0) { std::cout << "用户名密码验证失败。。" << std::endl; } std::cout << "成功" << std::endl; // 打开通道 // LIBSSH2_CHANNEL *channel = libssh2_channel_open_session(session); LIBSSH2_CHANNEL* channel = nullptr; while ((channel = libssh2_channel_open_session(session)) == NULL && libssh2_session_last_error(session, NULL, NULL, 0) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } if(!channel) { fprintf(stderr, "Unable to open a session\n"); return -1; } char modes[] = { 1, 0, 53, 1, 0 }; rc = 0; while ((rc = libssh2_channel_request_pty(channel, "xterm")) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } if (rc != 0) { fprintf(stderr, "Error\n"); exit(1); } // while (rc = libssh2_channel_setenv(channel, ) == LIBSSH2_ERROR_EAGAIN) // { // waitsocket(socketfd, session); // } // if (rc != 0) // { // fprintf(stderr, "Error\n"); // exit(1); // } // if(libssh2_channel_request_pty(channel, "xterm")) { // fprintf(stderr, "Failed requesting pty\n"); // } // // libssh2_channel_request_pty_size(channel, 10000, 100000); while ((rc = libssh2_channel_shell(channel)) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } if (rc != 0) { fprintf(stderr, "Error\n"); exit(1); } // while ((rc = libssh2_channel_write(channel, "stty echo\n", strlen("stty echo\n"))) == LIBSSH2_ERROR_EAGAIN) // { // waitsocket(socketfd, session); // } // // if (rc < 0) // { // fprintf(stderr, "Error\n"); // exit(1); // } while ((rc = libssh2_channel_write(channel, "system-view\ndisplay current-configuration\n", strlen("system-view\ndisplay current-configuration\n"))) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } if (rc < 0) { fprintf(stderr, "Error\n"); exit(1); } // 执行远程命令 // if(libssh2_channel_exec(channel, "PAGER=cat\nsystem-view\ndisplay current-configuration\n ")) { // fprintf(stderr, "Unable to request command on channel\n"); // return -1; // } // std::this_thread::sleep_for(std::chrono::seconds(3)); // if(libssh2_channel_shell(channel)) { // fprintf(stderr, "Unable to request shell on allocated pty\n"); // return -1; // } // // char b[1024*8]; // libssh2_channel_read(channel, b, sizeof(b)); // // std::cout << "cmd: " << b << std::endl; // // const char* cmd = "ls"; // libssh2_channel_write(channel, cmd, sizeof(cmd)); // // // libssh2_channel_read(channel, b, sizeof(b)); // // std::cout << "cmd: " << b << std::endl; // while ((rc = libssh2_channel_send_eof(channel)) == LIBSSH2_ERROR_EAGAIN) // { // waitsocket(socketfd, session); // } // if (rc < 0) // { // fprintf(stderr, "Error\n"); // exit(1); // } int bytecount = 0; constexpr std::size_t BACKUP_DATA_SIZE = 50 * 1024; // 备份数据区尺寸 char backupData[BACKUP_DATA_SIZE]; // 备份数据区 memset(backupData, 0, BACKUP_DATA_SIZE); // 重置备份数据区 char* backupDataPtr{backupData}; // 备份数据区指针 std::size_t readRetryCount{0}; // 读取重试次数 while (true) { // 判断重试次数是否超限(重试3次),如果超限则停止读取,表示备份完毕 if (readRetryCount >= 3) { libssh2_channel_close(channel); libssh2_channel_free(channel); libssh2_session_disconnect(session, "Normal Shutdown"); libssh2_session_free(session); LIBSSH2_SOCKET_CLOSE(socketfd); std::cout << "备份失败..." << std::endl; break; } // 通道读取缓存 constexpr std::size_t CHANNEL_BUFFER_SIZE = 1024 * 10; // 通道缓存区字节大小 char channelBuffer[CHANNEL_BUFFER_SIZE]; // 通道缓存区 memset(channelBuffer, 0, CHANNEL_BUFFER_SIZE); // 重置通道缓存区 // 已读到的字节数 std::int32_t readBytesCount{0}; do { // fprintf(stderr, "BackupData:\n"); // for (std::size_t i = 0; i < 10240; ++i) // fputc(backupData[i], stderr); // fprintf(stderr, "\n"); // 处理完数据后,重置缓存 memset(channelBuffer, 0, CHANNEL_BUFFER_SIZE); // 尝试读取数据 readBytesCount = libssh2_channel_read(channel, channelBuffer, CHANNEL_BUFFER_SIZE); std::cout << readBytesCount << std::endl; // 如果读取到了数据,则进行处理 if (readBytesCount > 0) { // 读到数据后,重置重试次数 readRetryCount = 0; std::cout << readRetryCount << std::endl; // 查看返回的字符串中,是否含有 More 符号 char* moreSymbolPtr = strstr(channelBuffer, "---- More ----"); // 如果存在more符号,则先过滤,再进行拷贝 if (moreSymbolPtr != NULL) { // backupDataPtr永远指向下一个空的区域 memcpy(backupDataPtr, channelBuffer, moreSymbolPtr - channelBuffer); // 移动备份数据指针到下一个空白区 backupDataPtr += (moreSymbolPtr - channelBuffer); // 如果包含了more符号,则继续向服务端发送换行符,继续读取 std::int32_t moreBytesCount{0}; while ((moreBytesCount = libssh2_channel_write(channel, " ", strlen(" "))) == LIBSSH2_ERROR_EAGAIN) { waitsocket(socketfd, session); } if (moreBytesCount < 0){ SPDLOG_INFO("向SSH服务端写入More指令失败.."); } // 继续下一次读取 continue; } // 将读到的数据,存储到备份数据中 memcpy(backupDataPtr, channelBuffer, readBytesCount); // 移动备份数据指针到下一个空白区 backupDataPtr += readBytesCount; } // 休息一会再读 // std::this_thread::sleep_for(std::chrono::milliseconds(50)); } while (readBytesCount > 0) ; // 如果这次读取到了数据,则继续下一次读取 // 如果这次尝试读取失败,看是否是服务端还未响应完,没响应完则等待 if (readBytesCount == LIBSSH2_ERROR_EAGAIN) { // 等待socket响应 waitsocket(socketfd, session); // 如果服务器确认响应完了,读取确认就是失败的了,则记录重试次数 readRetryCount ++; } } std::string s{backupData, static_cast(backupDataPtr-backupData)}; std::cout << s << std::endl; // 不断尝试读取服务端返回的内容 // while (true) // { // /* loop until we block */ // int rc{0}; // do // { // char buffer[0x4000]; // rc = libssh2_channel_read(channel, buffer, sizeof(buffer)); // // if (rc > 0) // { // int i; // bytecount += rc; // fprintf(stderr, "We read:\n"); // for (i = 0; i < rc; ++i) // fputc(buffer[i], stderr); // fprintf(stderr, "\n"); // // if (strstr(buffer, "---- More ----")) { // int m = 0; // while ((m = libssh2_channel_write(channel, "\n", strlen("\n"))) == LIBSSH2_ERROR_EAGAIN) // { // waitsocket(socketfd, session); // } // if (m < 0) // { // fprintf(stderr, "Error\n"); // exit(1); // } // } // } // else { // if (rc != LIBSSH2_ERROR_EAGAIN) // std::cout << "Hello World" << std::endl; // /* no need to output this for the EAGAIN case */ // fprintf(stderr, "libssh2_channel_read returned %d\n", rc); // } // // std::this_thread::sleep_for(std::chrono::milliseconds(50)); // } while (rc > 0); // // /* this is due to blocking that would occur otherwise so we loop on // this condition */ // if (rc == LIBSSH2_ERROR_EAGAIN) // { // waitsocket(socketfd, session); // } // else // break; // } // while(!libssh2_channel_eof(channel)) { // std::cout << "Hello World" << std::endl; // // char buf[1024]; // ssize_t err = libssh2_channel_read(channel, buf, sizeof(buf)); // if(err < 0) // fprintf(stderr, "Unable to read response: %ld\n", (long)err); // else { // fwrite(buf, 1, (size_t)err, stdout); // } // } // rc = libssh2_channel_get_exit_status(channel); if(libssh2_channel_close(channel)) fprintf(stderr, "Unable to close channel\n"); if(channel) { libssh2_channel_free(channel); channel = NULL; } if(session) { libssh2_session_disconnect(session, "Normal Shutdown"); libssh2_session_free(session); } if(socketfd != LIBSSH2_INVALID_SOCKET) { shutdown(socketfd, 2); LIBSSH2_SOCKET_CLOSE(socketfd); } // 在使用完libssh2库后,清理分配的资源 libssh2_exit(); #include #include #include #include #include #include #include void check_error(DBPROCESS* dbproc) { if (dbproc == NULL || dber(dbproc)) { fprintf(stderr, "DB-Library error:\n"); const int err = dbgetchar(); while (err != NO_MORE_ERRORS) { fprintf(stderr, "Error %d: %s\n", err, dberrstr(err)); } exit(EXIT_FAILURE); } } std::future future = std::async(std::launch::async, [&]() { // 初始化db库 std::size_t retCode = dbinit(); if (retCode == FAIL) { std::cout << "初始化失败" << std::endl; return; } // 创建登录对象 LOGINREC* login = dblogin(); if (login == NULL) { std::cout << "登录对象创建失败" << std::endl; return; } // 设定连接账号 DBSETLUSER(login, "testuser"); // 设定连接密码 DBSETLPWD(login, "!QAZ2wsx@123"); // 连接数据库服务器 DBPROCESS* dbproc = dbopen(login, "rm-bp1in5ro7jv6251oajo.sqlserver.rds.aliyuncs.com:3433"); // 切换到指定数据库 if (dbuse(dbproc, "dbtest") == FAIL) { std::cout << "数据库切换失败" << std::endl; return; } // 提交sql命令 std::string sql{"SELECT 1"}; if (dbcmd(dbproc, sql.c_str()) == FAIL) { std::cout << "先谢谢..." << std::endl; } // 执行sql命令 if (dbsqlexec(dbproc) == FAIL) { std::cout << "执行sql语句失败.." << std::endl; } // 回收资源 dbclose(dbproc); dbloginfree(login); dbexit(); }); // 1、加载mongoc驱动 mongoc_init(); // 2、创建MongoDB客户端 mongoc_client_t *client = mongoc_client_new("mongodb://127.0.0.1:27017"); // 如果连接失败 if (!client) { std::cout << "Failed to connect to mongodb://127.0.0.1:27017" << std::endl; return EXIT_FAILURE; } bson_t *ping = BCON_NEW ("ping", BCON_INT32 (1)); bson_t reply = BSON_INITIALIZER; bson_error_t error; // Send a ping to confirm a successful connection if (!mongoc_client_command_simple(client, "admin", ping, NULL, &reply, &error)) { fprintf(stderr, "error: %s\n", error.message); } std::cout << bson_get_data (&reply) << std::endl; bson_destroy (&reply); bson_destroy (ping); // mongoc_database_destroy (database); mongoc_client_destroy (client); // 清除mongoc驱动 mongoc_cleanup(); // PGconn *conn = PQconnectdb("host=192.168.0.102 port=5432 dbname=ganzhi user=postgres password=root"); // if (PQstatus(conn) == CONNECTION_BAD) { // fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn)); // // 处理连接失败的情况,例如退出程序 // exit(0); // } // const char *uri_string = "mongodb://localhost:27017"; // // 连接配置 // redisOptions options{0}; // options.type = REDIS_CONN_TCP; // 要求TCP方式连接 // options.endpoint.tcp.ip = "127.0.0.1"; // 目标redis服务地址 // options.endpoint.tcp.port = 6379; // 目标redis服务端口 // options.endpoint.tcp.source_addr = "192.168.0.110"; // 客户端地址 // options.options |= REDIS_OPT_PREFER_IPV4; // 在dns时,推荐查找ipv4 // options.options |= REDIS_OPT_REUSEADDR; // 重用本地地址 // // // 设置连接超时时间 // timeval connectTimeout{.tv_sec = 13, .tv_usec = 0}; // options.connect_timeout = &connectTimeout; // // // 设置命令执行的超时时间 // timeval commandTimeout{.tv_sec = 13, .tv_usec = 0}; // options.command_timeout = &commandTimeout; // // // 基础TCP连接 // redisContext* context = redisConnectWithOptions(&options); // // if (context == nullptr || context->err) { // std::cout << "RedisConnectWithOptions() failed." << context->errstr << std::endl; // if (context != nullptr) redisFree(context); // return 1; // } // // std::cout << "RedisConnectWithOptions() succeeded." << std::endl; // // // 发送指令 // redisReply* reply = static_cast(redisCommand(context, "PING")); // // 如果错误发生,reply会为null,并且context->err会被设置 // if (reply == nullptr || context->err) { // std::cout << "RedisCommand() failed." << std::endl; // if (context != nullptr) redisFree(context); // return 1; // } // // std::cout << "RedisCommand() succeeded." << reply->str << std::endl; // // // 释放响应 // freeReplyObject(reply); // // // 释放资源 // redisFree(context); // #include #include #include // #include // #include #include #include asio2::http_client client; client.bind_connect([&] { if (asio2::get_last_error()) printf("connect failure : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str()); else printf("connect success : %s %u\n", client.local_address().c_str(), client.local_port()); // connect success, send a request. if (!asio2::get_last_error()) { // http::web_request req4 = http::make_request("POST / HTTP/1.1\r\nHost: 192.168.0.1\r\n\r\n"); // req4.set(http::field::body, "Hello World"); // req4.version(http::field::ho) // req4.set(http::field::protocol, "text/html"); // req4.set(http::field::authorization, "basic "); // req4.set(http::field::user_agent, "Chrome"); // // req4.body(); // const char * msg = "GET / HTTP/1.1\r\n\r\n"; // client.async_send(msg); // http::web_request req = http::make_request(url); client.async_send("GET / HTTP/1.1\r\n\r\n"); } }); client.bind_recv([&](http::web_request& req, http::web_response& rep){ // print the whole response std::cout << rep << std::endl; // print the response body std::cout << rep.body() << std::endl; // convert the response body to string std::stringstream ss; ss << rep.body(); std::cout << ss.str() << std::endl; // Remove all fields req.clear(); req.set(http::field::user_agent, "Chrome"); req.set(http::field::content_type, "text/html"); // http::verb::post req.method(http::verb::get); req.keep_alive(true); req.target("/get_user?name=abc"); req.body() = "Hello World."; req.prepare_payload(); client.async_send(std::move(req)); }); client.async_start("baidu.com", 80); while (std::getchar() != '\n'); // // std::string s = "https://www.baidu.com"; // // std::string_view targetQuery = http::url_to_query(s); // // std::cout << targetQuery << std::endl; // // return 1; // // asio2::https_client client; // // // client.set_options(asio::ssl::context::no_compression); // client.set_auto_reconnect(false); // client.set_verify_mode(asio::ssl::verify_none); // // // client.set_verify_callback([](bool preverified, // // asio::ssl::verify_context& ctx) -> bool { // // return preverified; // // }); // // // // // // // client.set_cert_file( // // "ca.crt", // // "client.crt", // // "client.key", // // "123456"); // // // if (asio2::get_last_error()) // // std::cout << "load cert files failed: " << asio2::last_error_msg() << std::endl; // // // std::string target = "https://www.twetec.com/abc/222.php?gg=111&jj=22"; // // // // std::cout << http::url_to_path(target) << std::endl; // // std::cout << http::url_to_query(target) << std::endl; // // // // std::stringstream ss; // // ss << http::url_to_path(target); // // if (!http::url_to_query(target).empty()) { // // ss << "?" << http::url_to_query(target); // // } // // // // std::cout << ss.str() << std::endl; // // // // return 1; // // // client.set_connect_timeout(std::chrono::seconds(10)); // // client.bind_init([&] { // // 绑定请求从哪个网口发送 // asio::ip::tcp::endpoint endpoint(asio::ip::address_v4::from_string("192.168.0.108"), 0); // client.socket().bind(endpoint); // }); // // client.bind_recv([&](http::web_request& req, http::web_response& rep) // { // asio2::ignore_unused(req); // // auto basic_string = decompress_gzip(rep.base().body().text()); // // auto type = rep.base().base()[http::field::content_type]; // // std::string body{""}; // if (basic_string.find("charset=gb18030") != std::string::npos || basic_string.find("charset=gbk") != std::string::npos || basic_string.find("charset=GB2312") != std::string::npos) { // body = gbk_to_utf8(basic_string); // } // // std::cout << "----------------------------------------" << std::endl; // std::cout << type << std::endl; // std::cout << rep.base().base()[http::field::content_encoding] << std::endl; // // std::cout << basic_string << std::endl; // std::cout << "=========================================" << std::endl; // std::cout << body << std::endl; // // // }).bind_connect([&]() // { // if (asio2::get_last_error()) // printf("connect failure : %d %s\n", // asio2::last_error_val(), asio2::last_error_msg().c_str()); // else // printf("connect success : %s %u\n", // client.local_address().c_str(), client.local_port()); // // // 设置完响应调用后,发送然探测请求 (默认 http 1.1) // // http::web_request request = http::make_request( // // http::url_to_host(target), // // http::url_to_port(target), // // http::url_to_path(target), // // http::verb::get // // ); // // // // // // http::request request{http::verb::get, "/onebook.php?novelid=4398357", 11}; // // // request.set(http::field::host, "www.jjwxc.net"); // // request.set(http::field::user_agent, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"); // // request.set(http::field::accept, "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"); // // request.set(http::field::accept_encoding, "gzip, deflate, br, zstd"); // // request.prepare_payload(); // // // request.set(http::field::accept_charset, "UTF-8"); // // // request.set(http::field::accept_language, "zh-CN"); // // request.set(http::field::content_type, "text/html; charset=utf-8"); // // // request.set(http::field::cookie, "smidV2=20250726162406a5b323ad4bbf7eed25d69efbb8407d0d00d6cdf3d875f0be0; testcookie=yes; Hm_lvt_bc3b748c21fe5cf393d26c12b2c38d99=1753518246,1755914677; HMACCOUNT=DE30CEFB3539ABA3; timeOffset_o=-1044.60009765625; JJSESS=%7B%22clicktype%22%3A%22%22%7D; JJEVER=%7B%22shumeideviceId%22%3A%22WHJMrwNw1k/Hf9KOHQigisJQ1yR9Q6jWXtAFrMCR5OtEx2tUwFg45UmynmbOcIglk/e6hUNo4JWJGJ30aizPfo8lcAnib2tH9dCW1tldyDzmQI99+chXEimXk0foehC479lCUKKcsmkTaFO8webhNijYmmmXo8LlTkQE5YcNLqNriNYPfoOP/bkZ2IDwYrIyWFRRuSg/X1FURTkAd7H/eWg3vWKWV694HwWBNbiwpDzJz1fdaDkVLZrK5rfholf+0fUGgIqCuSLQ%3D1487582755342%22%7D; Hm_lpvt_bc3b748c21fe5cf393d26c12b2c38d99=1755916246"); // // // // send a request // client.async_send(request); // // client.async_send(request); // // }).bind_disconnect([]() // { // printf("disconnect : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str()); // }).bind_handshake([&]() // { // printf("handshake : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str()); // }); // // if (!client.async_start("www.jjwxc.net", "443")) // { // std::cout << "start failed : " << asio2::last_error_msg() << std::endl; // } // else // { // std::cout << "start success " << std::endl; // } // // // send data, beacuse may be connect failed, // // if connect failed, the data will sent failed too. // // client.async_send(std::string("abc0123456789xyz"), []() // // { // // if (asio2::get_last_error()) // // std::cout << "send failed : " << asio2::last_error_msg() << std::endl; // // }); // // while (std::getchar() != '\n'); #include #include #include using namespace std::string_literals; using namespace std::string_view_literals; static std::string decompress_gzip(const std::string& compressed) { z_stream zs; memset(&zs, 0, sizeof(zs)); // 使用 gzip 头部检测 if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK) { throw std::runtime_error("inflateInit2 failed"); } zs.next_in = (Bytef*)compressed.data(); zs.avail_in = compressed.size(); int ret; char outbuffer[32768]; std::string outstring; // 获取解压后的数据 do { zs.next_out = reinterpret_cast(outbuffer); zs.avail_out = sizeof(outbuffer); ret = inflate(&zs, 0); if (outstring.size() < zs.total_out) { outstring.append(outbuffer, zs.total_out - outstring.size()); } } while (ret == Z_OK); inflateEnd(&zs); if (ret != Z_STREAM_END) { std::ostringstream oss; oss << "Error during decompression (" << ret << ")"; throw std::runtime_error(oss.str()); } return outstring; } static std::string gbk_to_utf8(const std::string& gbk_str) { iconv_t cd = iconv_open("UTF-8", "GBK"); if(cd == (iconv_t)-1) return gbk_str; size_t in_len = gbk_str.size(); size_t out_len = in_len * 4; char* in_buf = const_cast(gbk_str.data()); std::string utf8_str(out_len, '\0'); char* out_buf = &utf8_str[0]; if(iconv(cd, &in_buf, &in_len, &out_buf, &out_len) == (size_t)-1) { iconv_close(cd); return gbk_str; } iconv_close(cd); utf8_str.resize(utf8_str.size() - out_len); return utf8_str; } s_iopool.post([this, handle] { // 线程锁 std::mutex mtx; std::condition_variable cv; // 发出请求 std::future future = std::async(std::launch::async, [this, &mtx, &cv] { try { // 发出请求,同步发出请求 asio2::icmpv4_rep rep = asio2::ping_ipv4::execute(m_interface, m_target, 8s, "HELLO"); // 加锁 std::unique_lock lock(mtx); // 保存延迟 m_delay = (rep.is_timeout() || rep.lag.count()==-1)? -1 : std::chrono::duration_cast(rep.lag).count(); // 通知延迟保存成功 cv.notify_one(); } catch (const std::exception &e) { // 加锁 std::unique_lock lock(mtx); // 保存延迟 m_delay = -1; // 通知延迟保存成功 cv.notify_one(); } }); // 等待响应(10s) std::unique_lock lock(mtx); std::cv_status cvStatus = cv.wait_for(lock, 10s); // 如果等待超时,则将延迟置为-1 if (cvStatus == std::cv_status::timeout) m_delay = -1; // 恢复暂停的协程 handle.resume(); }); s_iopool.submit_task([this, handle] { // 线程锁 std::mutex mtx; std::condition_variable cv; // 请求计时 - 开始时间 std::chrono::time_point probeStartTime = std::chrono::steady_clock::now(); // 发起探测 std::future future = std::async(std::launch::async, [this, &probeStartTime, &mtx, &cv] { // 创建UDP套接字 int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建失败时结束探测 if (sockfd < 0) { // 加锁 std::unique_lock lock(mtx); // 保存延迟 m_delay = -1; // 通知延迟保存成功 cv.notify_one(); // 结束执行 return; } // 设置接收超时 struct timeval tv; tv.tv_sec = 8000 / 1000; tv.tv_usec = (8000 % 1000) * 1000; if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { // 关闭socket close(sockfd); // 加锁 std::unique_lock lock(mtx); // 保存延迟 m_delay = -1; // 通知延迟保存成功 cv.notify_one(); // 结束执行 return; } // 设定网口地址 struct sockaddr_in interfaceAddr; memset(&interfaceAddr, 0, sizeof(interfaceAddr)); interfaceAddr.sin_family = AF_INET; interfaceAddr.sin_port = htons(0); if (inet_pton(AF_INET, m_interface.c_str(), &interfaceAddr.sin_addr) <= 0) { // 关闭socket close(sockfd); // 加锁 std::unique_lock lock(mtx); // 保存延迟 m_delay = -1; // 通知延迟保存成功 cv.notify_one(); // 结束执行 return; } // 绑定本机网口 if (bind(sockfd, (sockaddr *)&interfaceAddr, sizeof(interfaceAddr)) < 0) { // 关闭socket close(sockfd); // 加锁 std::unique_lock lock(mtx); // 保存延迟 m_delay = -1; // 通知延迟保存成功 cv.notify_one(); // 结束执行 return; } // 设置目标地址 struct sockaddr_in targetAddr; memset(&targetAddr, 0, sizeof(targetAddr)); targetAddr.sin_family = AF_INET; targetAddr.sin_port = htons(m_port); if (inet_pton(AF_INET, m_target.c_str(), &targetAddr.sin_addr) <= 0) { // 关闭socket close(sockfd); // 加锁 std::unique_lock lock(mtx); // 保存延迟 m_delay = -1; // 通知延迟保存成功 cv.notify_one(); // 结束执行 return; } // 连接服务器 if (connect(sockfd, (struct sockaddr *)&targetAddr, sizeof(targetAddr)) < 0) { // 关闭socket close(sockfd); // 加锁 std::unique_lock lock(mtx); // 保存延迟 m_delay = -1; // 通知延迟保存成功 cv.notify_one(); // 结束执行 return; } // 关闭socket close(sockfd); // 接收到数据,计算延迟 // 加锁 std::unique_lock lock(mtx); // 保存延迟 m_delay = std::chrono::duration_cast(std::chrono::steady_clock::now() - probeStartTime).count(); // 通知延迟保存成功 cv.notify_one(); }); // 等待响应(12s) std::unique_lock lock(mtx); std::cv_status cvStatus = cv.wait_for(lock, 10s); // 如果等待超时,则将延迟置为-1 if (cvStatus == std::cv_status::timeout) m_delay = -1; // 恢复暂停的协程 handle.resume(); }); // 创建UDP套接字 int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sockfd < 0) { std::cerr << "Socket creation failed" << std::endl; FAIL(); } // 设置发送超时 struct timeval sendTimeout; sendTimeout.tv_sec = 5000 / 1000; sendTimeout.tv_usec = (5000 % 1000) * 1000; if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &sendTimeout, sizeof(sendTimeout)) < 0) { perror("setsockopt SO_SNDTIMEO"); close(sockfd); FAIL(); } // 设置接收超时 struct timeval recvTimeout; recvTimeout.tv_sec = 5000 / 1000; recvTimeout.tv_usec = (5000 % 1000) * 1000; if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &recvTimeout, sizeof(recvTimeout)) < 0) { perror("setsockopt SO_SNDTIMEO"); close(sockfd); FAIL(); } // 设定目标地址 struct sockaddr_in dest_addr; memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.sin_family = AF_INET; if (inet_pton(AF_INET, "192.168.0.104", &dest_addr.sin_addr) <= 0) { std::cerr << "Invalid address" << std::endl; close(sockfd); FAIL(); } // 填充ICMP包 ICMPPacketIPv4 packet; memset(&packet, 0, sizeof(packet)); packet.header.type = ICMP_ECHO; packet.header.code = 0; packet.header.id = getpid() & 0xFFFF; strncpy(packet.payload, "Hello, this is a ping packet!", sizeof(packet.payload)-1); // printf("PING %s (%s): %d data bytes\n", dest_ip, dest_ip, // (int)(sizeof(packet) - sizeof(icmp_header_t))); packet.header.seq = 0; gettimeofday(&packet.timestamp, NULL); packet.header.checksum = 0; packet.header.checksum = computeICMPChecksumIPv4((unsigned short *)&packet, sizeof(packet)); // 发送ICMP包 if (sendto(sockfd, &packet, sizeof(packet), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) <= 0) { std::cout << "发送数据包失败.." << std::endl; FAIL(); } char recv_buf[1024]; struct sockaddr_in from_addr; socklen_t from_len = sizeof(from_addr); // 接收响应 ssize_t recv_len; struct timeval start_time, end_time; gettimeofday(&start_time, NULL); recv_len = recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&from_addr, &from_len); gettimeofday(&end_time, NULL); // 解析IP头获取ICMP包位置 struct iphdr *ip_header = (struct iphdr *)recv_buf; size_t ip_header_len = ip_header->ihl * 4; if (recv_len < ip_header_len + ICMP_MINLEN) { std::cout << "包长度不足" << std::endl; } struct icmphdr *icmp_header = (struct icmphdr *)(recv_buf + ip_header_len); // 检查是否是我们的响应 if (icmp_header->type == ICMP_ECHOREPLY && icmp_header->un.echo.id == packet.header.id) { double rtt = (end_time.tv_sec - start_time.tv_sec) * 1000.0 + (end_time.tv_usec - start_time.tv_usec) / 1000.0; printf("%d bytes from %s: icmp_seq=%d ttl=%d time=%.3f ms\n", (int)(recv_len - ip_header_len), inet_ntoa(from_addr.sin_addr), ntohs(icmp_header->un.echo.sequence), ip_header->ttl, rtt); // break; } close(sockfd); // // Created by twetec on 25-6-22. // #include "handle_icmp_probe_task.h" #include #include using namespace std::chrono_literals; namespace network_prober::probe { // 线程池 static BS::thread_pool s_iopool{3000}; // identifier的随机数生成器 static std::atomic_uint16_t s_identifierCounter{0}; // ICMPProbeIPv4::ICMPProbeIPv4(const std::string &interface, const std::string &target) // : m_interface{interface}, m_target{target}, m_iopool{1} // { // m_iopool.start(); // // m_pingPtr = std::make_unique(m_iopool.get(0)); // // // 一次ping的超时时间 // m_pingPtr->set_timeout(13s); // // 两次ping之间的间隔时间 // m_pingPtr->set_interval(20s); // // // 在socket初始化时调用 // m_pingPtr->bind_init([this]() { // // 绑定请求从哪个网口发送 // asio::ip::icmp::endpoint endpoint{asio::ip::address_v4::from_string(m_interface), 0}; // m_pingPtr->socket().bind(endpoint); // }); // } // // void ICMPProbeIPv4::probe() // { // // 发起请求 // m_pingPtr->start(m_target); // } // // void ICMPProbeIPv4::setOnProbedCallback(std::function&& callback) // { // m_onProbedCallback = callback; // // std::cout << "bind_recv: 外面" << std::this_thread::get_id() << std::endl; // // 请求响应时调用 // m_pingPtr->bind_recv([this](asio2::icmpv4_rep& rep) { // std::cout << "bind_recv: 里面" << std::this_thread::get_id() << std::endl; // m_onProbedCallback((rep.is_timeout() || rep.lag.count()==-1)? -1 : std::chrono::duration_cast(rep.lag).count()); // m_iopool.stop(); // }); // } // // // ICMPProbeIPv4::~ICMPProbeIPv4() // { // SPDLOG_INFO("yyyy 析构了.."); // // std::cout << "~ICMPProbeIPv4: " << std::this_thread::get_id() << std::endl; // // // m_iopool.stop(); // // // 停止探测 // // m_ping.wait_stop(); // // m_ping.destroy() // // m_ping.stop(); // // m_ping.destroy(); // } HandleICMPProbeIPv4Awaiter::HandleICMPProbeIPv4Awaiter(const database::ProbeTaskModel &probeTask) : m_interface{probeTask.interface}, m_target{probeTask.address} { } bool HandleICMPProbeIPv4Awaiter::await_ready() { return false; } void HandleICMPProbeIPv4Awaiter::await_suspend(std::coroutine_handle<> handle) { s_iopool.submit_task([this, handle] { // 线程锁 std::mutex mtx; std::condition_variable cv; // ICMP命令 std::shared_ptr pingPtr = std::make_shared(); // 连接超时时间 pingPtr->set_timeout(8s); // 请求发送间隔 pingPtr->set_interval(20s); // 设定程序标识 改变标识的值,给下一次观测使用(先load,再+1,再store) pingPtr->set_identifier(s_identifierCounter.fetch_add(1)); // socket open后调用,在这里 绑定请求从哪个网口发送 pingPtr->bind_init([this, pingPtr] { asio::ip::icmp::endpoint endpoint{asio::ip::address_v4::from_string(m_interface), 0}; pingPtr->socket().bind(endpoint); }); // 接收到响应后 pingPtr->bind_recv([this, pingPtr, &mtx, &cv](asio2::icmpv4_rep& rep){ // 加锁 std::unique_lock lock(mtx); // 保存延迟 m_delay = rep.nanoseconds(); // 通知延迟保存成功 cv.notify_one(); }); pingPtr->start(m_target); // 等待响应(12s) std::unique_lock lock(mtx); std::cv_status cvStatus = cv.wait_for(lock, 10s); // 停止请求 pingPtr->stop(); // 销毁内存 pingPtr->destroy(); // 如果等待超时,则将延迟置为-1 if (cvStatus == std::cv_status::timeout) m_delay = -1; // 继续执行 handle.resume(); }); } std::int64_t HandleICMPProbeIPv4Awaiter::await_resume() { return m_delay; } HandleICMPProbeIPv4Awaiter::~HandleICMPProbeIPv4Awaiter() { } // ICMPProbeIPv6::ICMPProbeIPv6(const std::string &interface, const std::string &target) // : m_interface(interface), m_target(target) // { // // 一次ping的超时时间 // m_ping.set_timeout(13s); // // 两次ping之间的间隔时间 // m_ping.set_interval(20s); // // // 在socket初始化时调用 // m_ping.bind_init([this]() { // // 绑定请求从哪个网口发送 // asio::ip::icmp::endpoint endpoint(asio::ip::address_v6::from_string(m_interface), 0); // m_ping.socket().bind(endpoint); // }); // } // // void ICMPProbeIPv6::probe() // { // // 发起请求 // m_ping.start(m_target); // } // // void ICMPProbeIPv6::setOnProbedCallback(std::function callback) // { // m_onProbedCallback = std::move(callback); // // // 返回一个指向当前对象的shared_ptr,并且计数器加了1 // auto self{shared_from_this()}; // // 响应时调用 // m_ping.bind_recv([this, self](asio2::icmpv6_rep& rep) { // // 回调 // m_onProbedCallback((rep.is_timeout() || rep.lag.count()==-1)? -1 : std::chrono::duration_cast(rep.lag).count()); // // 停止探测 // m_ping.stop(); // // 该代码块执行完, self被释放,当前对象计数器减1.释放当前对象 // }); // } // // ICMPProbeIPv6::~ICMPProbeIPv6() // { // m_ping.destroy(); // } HandleICMPProbeIPv6Awaiter::HandleICMPProbeIPv6Awaiter(const database::ProbeTaskModel &probeTask) : m_interface(probeTask.interface), m_target(probeTask.address) { } bool HandleICMPProbeIPv6Awaiter::await_ready() { return false; } void HandleICMPProbeIPv6Awaiter::await_suspend(std::coroutine_handle<> handle) { s_iopool.submit_task([this, handle] { // 线程锁 std::mutex mtx; std::condition_variable cv; // ICMP命令 std::shared_ptr pingPtr = std::make_shared(); // 连接超时时间 pingPtr->set_timeout(10s); // 请求发送间隔 pingPtr->set_interval(20s); // 设定程序标识 改变标识的值,给下一次观测使用(先load,再+1,再store) pingPtr->set_identifier(s_identifierCounter.fetch_add(1)); // // socket open后调用,在这里 绑定请求从哪个网口发送 // pingPtr->bind_init([this, pingPtr] { // asio::ip::icmp::endpoint endpoint{asio::ip::address_v6::from_string(m_interface), 0}; // pingPtr->socket().bind(endpoint); // }); // 接收到响应后 pingPtr->bind_recv([this, pingPtr, &mtx, &cv](asio2::icmpv6_rep& rep){ // 加锁 std::unique_lock lock(mtx); // 保存延迟 m_delay = rep.nanoseconds(); // 通知延迟保存成功 cv.notify_one(); }); pingPtr->start(m_target); // 等待响应(12s) std::unique_lock lock(mtx); std::cv_status cvStatus = cv.wait_for(lock, 12s); // 停止请求 pingPtr->stop(); // 销毁内存 pingPtr->destroy(); // 如果等待超时,则将延迟置为-1 if (cvStatus == std::cv_status::timeout) m_delay = -1; // 继续执行 handle.resume(); }); } std::int64_t HandleICMPProbeIPv6Awaiter::await_resume() { return m_delay; } } // 字符串位置 std::size_t searchStart = 0; std::size_t searchEnd = m_requestHeader.find("\n", searchStart); SPDLOG_INFO("kkk - m_requestHeader: {}", m_requestHeader); SPDLOG_INFO("kkk - searchEnd: {}", searchEnd); // 1、将整个header用\n分割为单独的条目 std::vector headerItems; headerItems.reserve(10); while (searchEnd != std::string::npos) { SPDLOG_INFO("kkk: start-{},end-{}, {}", searchStart, searchEnd, m_requestHeader.substr(searchStart, searchEnd - searchStart)); // 找到一个\n时,截取 headerItems.push_back(m_requestHeader.substr(searchStart, searchEnd - searchStart)); // 将start指向剩余的字符串 searchStart = searchEnd + 2; // 从新的start位置再次查找 searchEnd = m_requestHeader.find("\n", searchStart); } // 最后一段 headerItems.push_back(m_requestHeader.substr(searchStart)); // 2、将单独的条目用: 分割为key->value对 for (auto it = headerItems.begin(); it != headerItems.end(); ++it) { SPDLOG_INFO("请求头 - item: {}", *it); // 重置位置 searchStart = 0; searchEnd = it->find(": ", searchStart); std::string itemKey; while (searchEnd != std::string::npos) { itemKey = it->substr(searchStart, searchEnd - searchStart); searchStart = searchEnd + 2; searchEnd = it->find(": ", searchStart); } SPDLOG_INFO("请求头 - key: {} && value: {}", itemKey, it->substr(searchStart)); // 3、设置进请求头中 requestHeader.insert({itemKey, it->substr(searchStart)}); } s_iopool.submit_task([this, handle] { // 预设延迟未-1 m_delay = -1; // 尝试观测目标,若观测成功则设置m_delay,若观测失败则跳出循环 while (true) { // 创建UDP套接字 int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 创建失败时结束探测 if (sockfd < 0) { // 输出日志 SPDLOG_INFO("sockfd创建失败: {}", strerror(errno)); // 结束本次观测 break; } // 设置超时(3s) struct timeval timeout{3, 0}; // 发送超时 if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(struct timeval)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 发送超时设置时间失败: {}", sockfd, strerror(errno)); // 结束本次观测 break; } // 接收超时 if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(struct timeval)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 接收超时设置时间失败: {}", sockfd, strerror(errno)); // 结束本次观测 break; } // 允许绑定到尚未完全释放的端口 int reuse = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 重用网络端口设置时间失败: {}", sockfd, strerror(errno)); // 结束本次观测 break; } // 设定网口地址 struct sockaddr_in interfaceAddr; memset(&interfaceAddr, 0, sizeof(interfaceAddr)); interfaceAddr.sin_family = AF_INET; if (inet_pton(AF_INET, m_interface.c_str(), &interfaceAddr.sin_addr) <= 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 网口地址设置失败: {}", sockfd, strerror(errno)); // 结束本次观测 break; } // 绑定本机网口 if (bind(sockfd, (sockaddr *)&interfaceAddr, sizeof(interfaceAddr)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 网口地址绑定失败: {}", sockfd, strerror(errno)); // 结束本次观测 break; } // 设置目标地址 struct sockaddr_in targetAddr; memset(&targetAddr, 0, sizeof(targetAddr)); targetAddr.sin_family = AF_INET; targetAddr.sin_port = htons(m_port); if (inet_pton(AF_INET, m_target.c_str(), &targetAddr.sin_addr) <= 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 目标地址设置失败: {}", sockfd, strerror(errno)); // 结束本次观测 break; } // 请求计时 - 开始时间 std::chrono::time_point probeStartTime = std::chrono::steady_clock::now(); // 发送探测数据包 const char *message = "PING"; if (sendto(sockfd, message, strlen(message), 0, (const struct sockaddr *)&targetAddr, sizeof(targetAddr)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 探测数据包发送失败: {}", sockfd, strerror(errno)); // 结束本次观测 break; } // 尝试接收响应 char buffer[1024]; socklen_t len = sizeof(targetAddr); ssize_t recvdBytesCount = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&targetAddr, &len); // 关闭socket close(sockfd); // 如果未接收到数据 if (recvdBytesCount <= 0) { // 输出日志 // SPDLOG_INFO("sockfd: {} - 数据包接收失败: {}", sockfd, strerror(errno)); // 结束本次观测 break; } // 接收到数据,计算延迟 m_delay = std::chrono::duration_cast(std::chrono::steady_clock::now() - probeStartTime).count(); // 结束观测 break; } // 在m_delay计算完后,调度 handle.resume(); }); // 当socket套接字无效时,尝试3次 for (std::size_t i = 0; i < 3; i ++) { // 创建UDP套接字 int sockfd = socket(AF_INET6, SOCK_DGRAM, 0); if (sockfd < 0) { // 输出日志 SPDLOG_INFO("sockfd创建失败: {}", strerror(errno)); // 继续尝试获取套接字 continue; } // 设置超时 struct timeval timeout{2, 0}; // 发送超时 if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(struct timeval)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 发送超时设置时间失败: {}", sockfd, strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束本次观测 break; } // 接收超时 if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(struct timeval)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 接收超时设置时间失败: {}", sockfd, strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束本次观测 break; } // 设定网口地址 struct sockaddr_in6 interfaceAddr; memset(&interfaceAddr, 0, sizeof(interfaceAddr)); interfaceAddr.sin6_family = AF_INET6; interfaceAddr.sin6_port = htons(0); if (inet_pton(AF_INET6, m_interface.c_str(), &interfaceAddr.sin6_addr) <= 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 网口地址设置失败: {}", sockfd, strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束循环 break; } // 绑定本机网口 if (bind(sockfd, (sockaddr *)&interfaceAddr, sizeof(interfaceAddr)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 网口地址绑定失败: {}", sockfd, strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束循环 break; } // 设置目标地址 struct sockaddr_in6 targetAddr; memset(&targetAddr, 0, sizeof(targetAddr)); targetAddr.sin6_family = AF_INET6; targetAddr.sin6_port = htons(std::stoul(m_port)); if (inet_pton(AF_INET6, m_target.c_str(), &targetAddr.sin6_addr) <= 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 目标地址设置失败: {}", sockfd, strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束循环 break; } // 建立连接时,开始计时 std::chrono::time_point detectStartTime = std::chrono::steady_clock::now(); // 发送探测数据包 const char* message = "PING"; if (sendto(sockfd, message, strlen(message), 0, (const struct sockaddr*)&targetAddr, sizeof(targetAddr)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("探测数据包发送失败: {}", strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束循环 break; } // 尝试接收响应 char buffer[1024]; socklen_t len = sizeof(targetAddr); ssize_t recvdBytesCount = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&targetAddr, &len); // 关闭socket close(sockfd); // 如果未接收到数据 if (recvdBytesCount <= 0) { // 输出日志 SPDLOG_INFO("sockfd: {} - 数据包接收失败: {}", sockfd, strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束执行 break; } // 接收到数据,计算延迟 // 设置延迟 result.delay = std::chrono::duration_cast(std::chrono::steady_clock::now() - detectStartTime).count(); // 退出循环 break; } // 当socket套接字无效时 while (true) { // 创建UDP套接字 int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sockfd < 0) { // 输出日志 SPDLOG_INFO("sockfd创建失败: {}", strerror(errno)); // 继续尝试获取套接字 break; } // 设置超时(3s) struct timeval timeout{3, 0}; // 发送超时 if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(struct timeval)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 发送超时设置时间失败: {}", sockfd, strerror(errno)); // 结束本次观测 break; } // 接收超时 if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(struct timeval)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 接收超时设置时间失败: {}", sockfd, strerror(errno)); // 结束本次观测 break; } // 允许绑定到尚未完全释放的端口 int reuse = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 重用网络端口设置时间失败: {}", sockfd, strerror(errno)); // 结束循环 break; } // 设定网口地址 struct sockaddr_in interfaceAddr; memset(&interfaceAddr, 0, sizeof(interfaceAddr)); interfaceAddr.sin_family = AF_INET; interfaceAddr.sin_port = htons(0); if (inet_pton(AF_INET, m_interface.c_str(), &interfaceAddr.sin_addr) <= 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 网口地址设置失败: {}", sockfd, strerror(errno)); // 结束循环 break; } // 绑定本机网口 if (bind(sockfd, (sockaddr *)&interfaceAddr, sizeof(interfaceAddr)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 网口地址绑定失败: {}", sockfd, strerror(errno)); // 结束循环 break; } // 设置目标地址 struct sockaddr_in targetAddr; memset(&targetAddr, 0, sizeof(targetAddr)); targetAddr.sin_family = AF_INET; if (inet_pton(AF_INET, m_target.c_str(), &targetAddr.sin_addr) <= 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 目标地址设置失败: {}", sockfd, strerror(errno)); // 结束循环 break; } // 填充ICMP包 ICMPPacketIPv4 sendPacket; memset(&sendPacket, 0, sizeof(sendPacket)); sendPacket.header.type = ICMP_ECHO; sendPacket.header.code = 0; sendPacket.header.un.echo.id = s_identifierCounter.fetch_add(1); strncpy(sendPacket.payload, "PING", sizeof(sendPacket.payload)-1); // 准备校验和 sendPacket.header.un.echo.sequence = 0; gettimeofday(&sendPacket.timestamp, NULL); sendPacket.header.checksum = 0; sendPacket.header.checksum = computeICMPChecksumIPv4((unsigned short*)&sendPacket, sizeof(sendPacket)); // 请求计时 - 开始时间 std::chrono::time_point detectStartTime = std::chrono::steady_clock::now(); // 发送ICMP包 if (sendto(sockfd, &sendPacket, sizeof(sendPacket), 0, (struct sockaddr *)&targetAddr, sizeof(targetAddr)) <= 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - ICMP数据包发送失败: {}", sockfd, strerror(errno)); // 结束循环 break; } // 尝试接收响应 // ip头部 + icmp头部 + icmp数据 char recvBuf[1024]; socklen_t targetAddrLen = sizeof(targetAddr); // 接收响应数据的字节数 ssize_t recvdBytesCount = 0; // 尝试读取开始时间 std::chrono::time_point recvStartTime = std::chrono::steady_clock::now(); // 接收响应,如果接收到数据,进入循环体 do { // 尝试接收响应数据(阻塞) recvdBytesCount = recvfrom(sockfd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr *)&targetAddr, &targetAddrLen); // 如果在规定时间内,接收到数据 if (recvdBytesCount > 0) { // 解析IP头获取ICMP包位置 struct iphdr *ipHeader = (struct iphdr *)recvBuf; size_t ipHeaderLen = ipHeader->ihl * 4; // 如果包长度不够,则说明接收失败 if (recvdBytesCount < ipHeaderLen + ICMP_MINLEN) { // 输出日志 SPDLOG_INFO("sockfd: {} - ICMP数据包长度不够: {}", sockfd, strerror(errno)); // 继续尝试读取 continue; } // 提取icmp协议头 (跳过ip头) struct icmphdr *icmpHdr = (struct icmphdr *)(recvBuf + ipHeaderLen); // 检查是否是我们的响应 if (icmpHdr->type == ICMP_ECHOREPLY && icmpHdr->un.echo.id == sendPacket.header.un.echo.id) { // 关闭socket close(sockfd); // 计算延迟 m_delay = std::chrono::duration_cast(std::chrono::steady_clock::now() - detectStartTime).count(); // 输出日志 // SPDLOG_INFO("观测任务执行成功: {} 延迟", m_delay); // 结束接收 break; } } // 检查读取时间是否超时 if (std::chrono::duration_cast((std::chrono::steady_clock::now() - recvStartTime)) >= 6s) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("接收超时.."); // 终止尝试获取响应 break; } } while (recvdBytesCount > 0); // 当前读到了数据,就再尝试读取一次,直到当前这次读不到数据为止 // 关闭socket close(sockfd); // 结束循环 break; } /** * icmp ipv4 协议头 */ // typedef struct // { // std::uint8_t type; // 类型(8=请求,0=应答) // std::uint8_t code; // 代码(通常为0) // std::uint16_t checksum; // 校验和 // std::uint16_t id; // 标识符 // std::uint16_t seq; // 序列号 // } ICMPHeaderIPv4; typedef struct { struct icmphdr header; // icmp v4 协议头 struct timeval timestamp; // 时间戳 char payload[56]; // 负载 } ICMPPacketIPv4; unsigned short computeICMPChecksumIPv4(unsigned short* addr, int len) { int nleft = len; // 数据包字节长度,用于计数未经过计算的字节数 int sum = 0; unsigned short* w = addr; // 数据包指针 unsigned short answer = 0; // 16位 // 计算报文中两个字节的和 while (nleft > 1) { sum += *w++; // 1、从数据包中取16位;2、将取出的16位累加到和中 3、指针再移动16位,指向下两个要累加的数据字节内存 nleft -= 2; // 将未计算的字节数减少2个,直到只剩1或0个字节 } // 如果报文长度是奇数,最后一个字节作为高8位,再用0填充1个字节(低8位) if (nleft == 1) { *(unsigned char *)(&answer) = *(unsigned char *)w; // 把16位类型指针转为8位类型指针,取剩下的1个字节复制给answer sum += answer; // 将低位累加 } sum = (sum >> 16) + (sum & 0xffff); // 高16位 + 低16位 = sum只剩16位 sum += (sum >> 16); answer = ~sum; return answer; } // 当socket套接字无效时,尝试3次 for (std::size_t i = 0; i < 3; i ++) { // 创建UDP套接字 int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sockfd < 0) { // 输出日志 SPDLOG_INFO("sockfd创建失败: {}", strerror(errno)); // 继续尝试获取套接字 continue; } // 设置超时 struct timeval timeout{2, 0}; // 发送超时 if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(struct timeval)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 发送超时设置时间失败: {}", sockfd, strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束本次观测 break; } // 接收超时 if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(struct timeval)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 接收超时设置时间失败: {}", sockfd, strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束本次观测 break; } // 设定网口地址 struct sockaddr_in interfaceAddr; memset(&interfaceAddr, 0, sizeof(interfaceAddr)); interfaceAddr.sin_family = AF_INET; if (inet_pton(AF_INET, m_interface.c_str(), &interfaceAddr.sin_addr) <= 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 网口地址设置失败: {}", sockfd, strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束循环 break; } // 绑定本机网口 if (bind(sockfd, (sockaddr *)&interfaceAddr, sizeof(interfaceAddr)) < 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 网口地址绑定失败: {}", sockfd, strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束循环 break; } // 设置目标地址 struct sockaddr_in targetAddr; memset(&targetAddr, 0, sizeof(targetAddr)); targetAddr.sin_family = AF_INET; if (inet_pton(AF_INET, m_target.c_str(), &targetAddr.sin_addr) <= 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - 目标{}地址设置失败: {}", sockfd, m_target, strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束循环 break; } // 填充ICMP包 ICMPPacketIPv4 sendPacket; memset(&sendPacket, 0, sizeof(sendPacket)); sendPacket.header.type = ICMP_ECHO; sendPacket.header.code = 0; sendPacket.header.un.echo.id = s_identifierCounter.fetch_add(1); strncpy(sendPacket.payload, "PING", sizeof(sendPacket.payload)-1); // 准备校验和 sendPacket.header.un.echo.sequence = 0; gettimeofday(&sendPacket.timestamp, NULL); sendPacket.header.checksum = 0; sendPacket.header.checksum = computeICMPChecksumIPv4((unsigned short*)&sendPacket, sizeof(sendPacket)); // 请求计时 - 开始时间 std::chrono::time_point detectStartTime = std::chrono::steady_clock::now(); // 发送ICMP包 if (sendto(sockfd, &sendPacket, sizeof(sendPacket), 0, (struct sockaddr *)&targetAddr, sizeof(targetAddr)) <= 0) { // 关闭socket close(sockfd); // 输出日志 SPDLOG_INFO("sockfd: {} - ICMP数据包发送失败: {}", sockfd, strerror(errno)); // 判断错误是否是套接字 if (errno == EBADF) continue; // 结束循环 break; } // 尝试接收响应 // ip头部 + icmp头部 + icmp数据 char recvBuf[1024]; socklen_t targetAddrLen = sizeof(targetAddr); // 接收响应数据的字节数 ssize_t recvdBytesCount = 0; // 尝试读取开始时间 std::chrono::time_point recvStartTime = std::chrono::steady_clock::now(); // 接收响应,如果接收到数据,进入循环体 do { // 尝试接收响应数据(阻塞) recvdBytesCount = recvfrom(sockfd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr *)&targetAddr, &targetAddrLen); // 如果在规定时间内,接收到数据 if (recvdBytesCount > 0) { // 解析IP头获取ICMP包位置 struct iphdr *ipHeader = (struct iphdr *)recvBuf; size_t ipHeaderLen = ipHeader->ihl * 4; // 如果包长度不够,则说明接收失败 if (recvdBytesCount < ipHeaderLen + ICMP_MINLEN) { // 输出日志 SPDLOG_INFO("sockfd: {} - ICMP数据包长度不够: {}", sockfd, strerror(errno)); // 继续尝试读取 continue; } // 提取icmp协议头 (跳过ip头) struct icmphdr *icmpHdr = (struct icmphdr *)(recvBuf + ipHeaderLen); // 检查是否是我们的响应 if (icmpHdr->type == ICMP_ECHOREPLY && icmpHdr->un.echo.id == sendPacket.header.un.echo.id) { // 计算延迟 result.delay = std::chrono::duration_cast(std::chrono::steady_clock::now() - detectStartTime).count(); // 关闭socket close(sockfd); // 结束接收 break; } } // 检查读取时间是否超时 if (std::chrono::duration_cast((std::chrono::steady_clock::now() - recvStartTime)) >= 3s) { // 输出日志 SPDLOG_INFO("接收超时.."); // 关闭socket close(sockfd); // 终止尝试获取响应 break; } } while (recvdBytesCount > 0); // 当前读到了数据,就再尝试读取一次,直到当前这次读不到数据为止 // 关闭socket close(sockfd); // 结束循环 break; } /** * icmp ipv4 协议头 */ // typedef struct // { // std::uint8_t type; // 类型(8=请求,0=应答) // std::uint8_t code; // 代码(通常为0) // std::uint16_t checksum; // 校验和 // std::uint16_t id; // 标识符 // std::uint16_t seq; // 序列号 // } ICMPHeaderIPv4; typedef struct { struct icmphdr header; // icmp v4 协议头; // icmp v4 协议头 struct timeval timestamp; // 时间戳 char payload[56]; // 负载 } ICMPPacketIPv4; unsigned short computeICMPChecksumIPv4(unsigned short* addr, int len) { int nleft = len; // 数据包字节长度,用于计数未经过计算的字节数 int sum = 0; unsigned short* w = addr; // 数据包指针 unsigned short answer = 0; // 16位 // 计算报文中两个字节的和 while (nleft > 1) { sum += *w++; // 1、从数据包中取16位;2、将取出的16位累加到和中 3、指针再移动16位,指向下两个要累加的数据字节内存 nleft -= 2; // 将未计算的字节数减少2个,直到只剩1或0个字节 } // 如果报文长度是奇数,最后一个字节作为高8位,再用0填充1个字节(低8位) if (nleft == 1) { *(unsigned char *)(&answer) = *(unsigned char *)w; // 把16位类型指针转为8位类型指针,取剩下的1个字节复制给answer sum += answer; // 将低位累加 } sum = (sum >> 16) + (sum & 0xffff); // 高16位 + 低16位 = sum只剩16位 sum += (sum >> 16); answer = ~sum; return answer; } typedef struct { struct icmp6_hdr header; // icmp v4 协议头 struct timeval tv; // 时间戳 char payload[64-sizeof(icmp6_hdr)]; // 负载 } ICMPPacketIPv6; unsigned short computeICMPChecksumIPv6(unsigned short* addr, int len) { int nleft = len; // 数据包字节长度,用于计数未经过计算的字节数 int sum = 0; unsigned short* w = addr; // 数据包指针 unsigned short answer = 0; // 16位 // 计算报文中两个字节的和 while (nleft > 1) { sum += *w++; // 1、从数据包中取16位;2、将取出的16位累加到和中 3、指针再移动16位,指向下两个要累加的数据字节内存 nleft -= 2; // 将未计算的字节数减少2个,直到只剩1或0个字节 } // 如果报文长度是奇数,最后一个字节作为高8位,再用0填充1个字节(低8位) if (nleft == 1) { *(unsigned char *)(&answer) = *(unsigned char *)w; // 把16位类型指针转为8位类型指针,取剩下的1个字节复制给answer sum += answer; // 将低位累加 } sum = (sum >> 16) + (sum & 0xffff); // 高16位 + 低16位 = sum只剩16位 sum += (sum >> 16); answer = ~sum; return answer; } -w: WORKDIR sudo docker container run -it --rm -v "$(pwd)":/home/ubuntu/ganzhi/develop/code/prober -w /home/ubuntu/ganzhi/develop/code/prober x1