【问题标题】:How can I check data in boost asio socket with timeout如何使用超时检查boost asio套接字中的数据
【发布时间】:2019-02-24 18:12:28
【问题描述】:

如果 boost::asio::socket 的缓冲区中有一些数据,我该如何读取? 检查应该阻止程序的执行,直到达到超时。 我发现可以使用该功能

boost::asio::socket_base::bytes_readable

但 is 似乎是一个非阻塞操作,运行时不检查任何超时。 我不想使用 async_read 但如果有一些数据要读取,则直接读取套接字

【问题讨论】:

  • 这对我来说似乎是一种奇怪的使用模式。如果您可以扩展您的用例,我很确定有人可以提供更适合提升的替代方案。

标签: c++ sockets boost-asio tclientsocket


【解决方案1】:

您只需使用事件循环使该套接字变为非阻塞并等待套接字准备好读取或超时。

【讨论】:

    【解决方案2】:

    阻止程序在套接字中等待某些字节的执行的一种简单方法是将函数置于监视经过时间的while循环中。 下面是一个简单的解决方案:

    • 连接服务器
    • 从服务器读取。如果没有可读取的内容,请等待超时
    • 查看服务器消息并回复

    int find_char(char* buffer, size_t size_out, char chr)

    #include <boost/asio.hpp>  
    
    int main () {
        const int MAX_BUFFER_SIZE = 1024; //max size of buffer
        const char PACKET_END     = static_cast<char>(0xFF); //character that identifies the end of a packet
    
        //creation of Client Socket
        boost::asio::io_service ios;
        boost::asio::ip::tcp::socket client_socket(ios);
    
        //creation of endpoint connection
        std::string host_ip = "199.01.00.00";
        int port_number   = 2000;                    
        boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(host_ip), port_number);
    
        //connect client socket to server
        boost::system::error_code error_connection;         //connection error
    
        //conect to server
        bool is_connected = false;
        client_socket.connect(endpoint, error_connection);
        if(!error_connection)
            is_connected = true;
    
        //read from server buffer
        if (is_connected == true) { //connected
    
            //create empty buffer to store from server
            char buffer[MAX_BUFFER_SIZE];
            std::fill(buffer, buffer + sizeof(buffer), 0);
    
            //TCPIP read from buffer
            boost::system::error_code error_read;
    
            //initialize Timeout variables
            int timeout = 5000000; //timeout of 5 seconds [microsec]
            boost::posix_time::time_duration difference;        //elapsed time
            boost::posix_time::time_duration time_to_read;      //duration of reading
            boost::posix_time::ptime start_try_read = boost::posix_time::microsec_clock::local_time(); //save initial time to read
    
            //understand if there is something to read
            size_t bytes_readable = 0;
            bool something_to_read = false; //check if something to read
            do {
                    boost::posix_time::ptime start_read = boost::posix_time::microsec_clock::local_time(); //save initial time to try read
    
                    boost::asio::socket_base::bytes_readable num_bytes_readable(true);
                    client_socket.io_control(num_bytes_readable, error_read);
                    bytes_readable = num_bytes_readable.get(); //get the value of readable data
    
                    if ( bytes_readable > 0 ){
                        //found something to read
                        something_to_read = true;
                        break;
                    }
                    if (error_read == boost::asio::error::not_connected){
                        //server disconnected
                        is_connected = false;
                        something_to_read = false;
                        break;
                    }
                    boost::posix_time::ptime end_read = boost::posix_time::microsec_clock::local_time(); //save final time to try read
                    time_to_read = end_read - start_read;
                    difference = end_read - start_try_read;
            } while ( difference + time_to_read < boost::posix_time::microsec(time_out) && bytes_readable <= 0 );
    
            if (is_connected == true && difference + time_to_read >= boost::posix_time::microsec(time_out)) {
                //nothing to read, timeout
                something_to_read = false;
            } 
            else if (is_connected == true && !error_read && bytes_readable > 0) {
    
                //prepare to store the buffer
                char buffer_socket[bytes_readable + 1];
                std::fill(buffer_socket, buffer_socket + sizeof(buffer_socket), 0);
    
                //read from buffer the readable bytes amount and store
                boost::asio::read(client_socket, boost::asio::buffer(buffer_socket, bytes_readable));
    
                //check if message contains special character
                int position_end = find_char(buffer_socket, sizeof(buffer_socket), static_cast<char>(PACKET_END));
    
                //in case found an interesting message, reply to server
                if (position_end >= 0){
                    std::memcpy(buffer, buffer_socket, position_end + 1); //found interesting message, store it
                    //write response to server socket
                    char response[100] = "received good message";
                    boost::system::error_code error_write;
                    boost::asio::write(client_socket, boost::asio::buffer((char*)ct_request_buffer, sizeof(ct_request_buffer)), error_write);
                }
            }
        }
    }
    int find_char(char* buffer, size_t size_out, char chr){
        int pos = -1;
        size_t i = size_out - 1;
        while (i >= 0){
            if (buffer[i] == chr){
                pos = i;
                break;
            }
            i--;
        }return pos;
    }
    

    【讨论】:

    • 可以使用相同的方法尝试连接,直到超时结束
    猜你喜欢
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 2010-09-22
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多