2013-04-10 1 views
0

슬프게도 부스트 :: asio :: ip :: tcp :: acceptor가 얼마나 정확한지 이해할 수 없기 때문에 슬픈 듯이 개발에 착수했다. 익숙한. TCPReader 클래스는 싱글 톤으로 설계되었으며 헤더는 private로 다음을 선언합니다. boost :: asio acceptor가 다시 열리고 EOF 이후에 async가 읽힌다.

< <

TCPReader::TCPReader() : sock(io_service), 
         runningService(io_service), 
         acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), TCPPort)){ 
    this->isConnected = false; 

    acceptor.async_accept(sock, boost::bind(&TCPReader::accept_handler, this, boost::asio::placeholders::error)); 
    boost::thread thread(boost::bind(&TCPReader::runInThread, this)); 
} 


void TCPReader::runInThread(){ 
    io_service.run(); 
} 

read_handler가 EOF 또는 다른 오류를 수신 할 때까지 매력처럼 read_handler 및 모든 작품을 트리거보다 accept_handler

void runInThread(); 

void read_handler(const boost::system::error_code &ec, std::size_t bytes_transferred); 

void accept_handler(const boost::system::error_code &ec); 

boost::asio::io_service io_service; 
boost::asio::io_service::work runningService; 
boost::asio::ip::tcp::socket sock; 
boost::asio::ip::tcp::acceptor acceptor; 

bool isConnected; 
. 내가 원했던 것은 acceptor를 초기화 후에 연결을 받아 들일 수있는 상태로 되돌려 놓는 것이다. 나는 또는 cancel()을 다음과 같이 open(), listen()async_accept (생성자에서와 같이) 시도했습니다. 그러나 모든 것이 효과가없는 것 같습니다. 도움을 많이 주시면 감사하겠습니다.

답변

3

이 아닌 sock에서 오류가 발생했습니다. 따라서 acceptor의 상태가 영향을받지 않아야합니다. sock이 초기 닫힌 상태에있는 상태에서 async_accept 작업을 시작하면됩니다. 여기

가 포트 12345에서 수신 대기 완전한 기본적인 예입니다

#include <iostream> 

#include <boost/array.hpp> 
#include <boost/asio.hpp> 

using boost::asio::ip::tcp; 

class tcp_reader 
{ 
public: 
    tcp_reader(boost::asio::io_service& io_service) 
    : io_service_(io_service), 
     socket_(io_service), 
     acceptor_(io_service, 
       tcp::endpoint(tcp::v4(), 12345)) 
    { 
    accept_connection(); 
    } 

private: 

    void accept_connection() 
    { 
    std::cout << "accepting connection" << std::endl; 
    // Verify socket is in a closed state. 
    socket_.close(); 
    // On success or failure, acceptor will open() socket_. 
    acceptor_.async_accept(socket_, 
     boost::bind(&tcp_reader::handle_accept, this, 
        boost::asio::placeholders::error)); 
    } 

    void handle_accept(const boost::system::error_code& error) 
    { 
    // On error, return early. 
    if (error) 
    { 
     std::cout << "handle_accept: " << error.message() << std::endl; 
     return; 
    } 

    // Start reading from socket. 
    read();  
    } 

    void read() 
    { 
    std::cout << "reading from socket" << std::endl; 
    async_read(socket_, boost::asio::buffer(buffer_), 
     boost::asio::transfer_at_least(1), 
     boost::bind(&tcp_reader::handle_read, this, 
        boost::asio::placeholders::error, 
        boost::asio::placeholders::bytes_transferred)); 
    } 

    void handle_read(const boost::system::error_code& error, 
        std::size_t bytes_transferred) 
    { 
    // On error, go back to listening for a new connection. 
    if (error) 
    { 
     std::cout << "handle_read: " << error.message() << std::endl; 
     accept_connection(); 
     return; 
    } 

    // Output read data. 
    std::cout.write(&buffer_[0], bytes_transferred); 

    // Read data, so read some more. 
    read(); 
    } 

private: 
    boost::asio::io_service& io_service_; 
    tcp::socket    socket_; 
    tcp::acceptor   acceptor_; 
    boost::array<char, 1024> buffer_; 
}; 

int main() 
{ 
    boost::asio::io_service io_service; 
    tcp_reader reader(io_service); 
    io_service.run(); 
} 

을 사용하여, 나는 하나 개의 터미널에서 그것을 실행하고 포트 12345에 연결, 메시지를 보낼 연결을 살해 한 후 연결을 다시 설정 .

[[email protected]]$ ./a.out 
accepting connection 
reading from socket 
hello 
reading from socket 
goodbye 
reading from socket 
handle_read: End of file 
accepting connection 
reading from socket 
oh, oh no 
reading from socket 
handle_read: End of file 
accepting connection 
ctrl + c

및 클라이언트 콘솔 : 서버는 다음과 같이 콘솔 출력했다

[[email protected]]$ nc 127.0.0.1 12345 
hello   
goodbye 
ctrl + c 
[[email protected]]$ nc 127.0.0.1 12345 
oh, oh no 
ctrl + c

인식하는 하나 개의 행동 세부 사항은 async_accept 작업을하지 않을 수 있지만에 계류중인 것입니다 acceptor_, 연결이 계속 대기 중입니다. 따라서 연결이 이미 수락되었고 다른 클라이언트가 연결을 시도하면 후자의 클라이언트는 연결 대기 중으로 받아 들여집니다. 이것이 바람직한 동작이 아니라면, 수락자는 close()을 통해 청취 상태에서 벗어나야합니다. This 응답 다이어그램은 상태 전이를 설명하고 수용기 동작의 일부를보다 자세히 설명합니다.

+0

대단히 감사합니다 :) 내 하루를 구 했어요! :) – dos