1

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

boost::asio::socket_base::bytes_readable

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

4

2 回答 2

0

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

于 2019-02-25T12:10:53.280 回答
-1

阻止程序执行等待套接字中的某些字节的一种简单方法是将函数置于监视经过时间的 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;
}
于 2019-02-24T18:12:28.557 回答