Как проверить данные в boost asio socket с тайм-аутом - PullRequest
0 голосов
/ 24 февраля 2019

Как я могу прочитать, если в буфере boost :: asio :: socket есть данные?Проверка должна блокировать выполнение программы до истечения времени ожидания.Я обнаружил, что можно использовать функцию

boost::asio::socket_base::bytes_readable

, но, похоже, это неблокирующее действие, которое выполняется без проверки тайм-аута.Я не хочу использовать async_read, но напрямую читаю сокет, если есть данные для чтения

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Вы просто делаете этот сокет неблокирующим и ждете, пока сокет не будет готов для чтения или тайм-аута, используя цикл обработки событий.

0 голосов
/ 24 февраля 2019

Один простой способ заблокировать выполнение программы, ожидающей несколько байтов в сокете, - поместить функцию в цикл while, который контролирует истекшее время.Ниже приведено простое решение, которое будет:

  • подключаться к серверу
  • читать с сервера.Если нечего читать, подождите до истечения времени ожидания
  • , проверьте сообщение сервера и ответьте

int find_char (char * буфер, 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;
}
...