简体   繁体   中英

How can I check data in boost asio socket with timeout

How can I read if there is some data in a buffer of boost::asio::socket? The check should block the execution of the program till a timeout is reached. I found out that it is possible to use the function

boost::asio::socket_base::bytes_readable

but is seems to be a non-blocking action that runs without checking any timeout. I don't want to use async_read but directly read the socket if there is some data to read

您只需使用事件循环使该套接字变为非阻塞状态,然后等待该套接字准备好进行读取或超时即可。

one easy way to block the execution of the program waiting for some bytes in the socket is to put the function in a while cycle that monitors the elapsed time. Here below a simple solution that will:

  • connect to server
  • read from server. If nothing to read, wait until timeout
  • check server message and reply

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM