2009-06-16 3 views
3

안녕하세요, 저는 asio와 boost를 처음 접했습니다. TCP 서버 & 클라이언트를 구현하여 표준을 전송할 수있었습니다. 벡터 -하지만 지금까지 실패했습니다. 나는 Asio의 부족한 문서가 부족하다는 것을 알고 있고 이해하기 어렵다. (영어는 제 1 언어가 아니다.)Boost :: Asio :: Ip :: Tcp :: Iostream 질문

어쨌든 iostreams 예제를 살펴 봤는데 객체 지향 솔루션을 구현하려고했지만 실패했습니다.

서버는 표준 : : 벡터를 받아야한다

나는 (내가 그걸 어떻게해야합니까?) 여러 클라이언트의 연결을 받아 들일 수 있어야 구현하기 위해 노력하고있어 서버/* 무언가를 */클라이언트가 서버로 데이터를 수신했다는 것을 알 수 있도록 클라이언트로 리턴하십시오.

* .H 파일

class TCP_Server : private boost::noncopyable 
     { 
      typedef boost::shared_ptr<TCP_Connection> tcp_conn_pointer; 

      public : 
       TCP_Server(ba::io_service &io_service, int port); 
       virtual ~TCP_Server() {} 
       virtual void Start_Accept(); 
      private: 
       virtual void Handle_Accept(const boost::system::error_code& e); 
      private : 
       int     m_port; 
       ba::io_service&  m_io_service;    // IO Service 
       bi::tcp::acceptor m_acceptor;   // TCP Connections acceptor 
       tcp_conn_pointer m_new_tcp_connection; // New connection pointer 
     }; 

* .cpp 파일

TCP_Server::TCP_Server(boost::asio::io_service &io_service, int port) : 
      m_io_service(io_service), 
      m_acceptor(io_service, bi::tcp::endpoint(bi::tcp::v4(), port)), 
      m_new_tcp_connection(TCP_Connection::Create(io_service)) 
     { 
      m_port = port; 
      Start_Accept(); 
     } 

     void TCP_Server::Start_Accept() 
     { 
      std::cout << "[TCP_Server][Start_Accept] => Listening on port : " << m_port << std::endl; 
      //m_acceptor.async_accept(m_new_tcp_connection->Socket(), 
      //      boost::bind(&TCP_Server::Handle_Accept, this, 
      //         ba::placeholders::error)); 


       m_acceptor.async_accept(*m_stream.rdbuf(), 
       boost::bind(&TCP_Server::Handle_Accept, 
       this, 
       ba::placeholders::error)); 
     } 

     void TCP_Server::Handle_Accept(const boost::system::error_code &e) 
     { 
      if(!e) 
      { 

       /*boost::thread T(boost::bind(&TCP_Connection::Run, m_new_tcp_connection)); 
       std::cout << "[TCP_Server][Handle_Accept] => Accepting incoming connection. Launching Thread " << std::endl; 
       m_new_tcp_connection = TCP_Connection::Create(m_io_service); 
       m_acceptor.async_accept(m_new_tcp_connection->Socket(), 
             boost::bind(&TCP_Server::Handle_Accept, 
                this, 
                ba::placeholders::error));*/ 
       m_stream << "Server Response..." << std::endl; 
      } 
     } 

어떻게 클라이언트가해야 할 것은? 두 앱이 모두 대화하는 동안 연결을 유지하려면 어떻게해야합니까?

답변

1

내가 게시 한 코드가 다소 불완전하거나 부정확하다고 생각합니다. 그럼에도 불구하고 여기에 몇 가지 지침이 있습니다.

1) async_accept() 호출이 잘못되었습니다. 그것은 Handle_Accept() 함수가 소켓이 허용됩니다 후 를 호출 할 것이다

m_acceptor.async_accept(m_new_tcp_connection->socket(),...) 

2) 를 적어 둡니다, 같은 것을해야한다. 즉, 컨트롤이 Handle_Accept()에 도달하면 소켓에 쓰기 만하면됩니다.

void TCP_Server::Handle_Accept(const system::error_code& error) 
{ 
    if(!error) 
    { 
    //send data to the client 
    string message = "hello there!\n"; 

    //Write data to the socket and then call the handler AFTER that 
    //Note, you will need to define a Handle_Write() function in your TCP_Connection class. 
async_write(m_new_tcp_connection->socket(),buffer(message),bind(&TCP_Connection::Handle_Write, this,placeholders::error,placeholders::bytes_transferred)); 

    //accept the next connection 
    Start_Accept(); 
    } 
} 
클라이언트에 관해서는

3) 비슷해, 여기 살펴 보셔야합니다 : 양쪽에 의사 소통 당신이 벡터를 sezilize하는 부스트 직렬화 라이브러리를 사용하여 C++로 구현되어있는 경우 http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/tutorial/tutdaytime1.html

1

바이트로 변환하여 다른 컴퓨터로 전송합니다. 반대편에서는 boost serialization lib를 사용하여 객체를 desirialize합니다. 나는 적어도 두 가지 접근법을 보았다.

부스트 직렬화의 장점 :이 접근법은 32 비트와 64 비트 시스템간에 객체를 전송할 때도 작동합니다.

는 아래 링크입니다 :
code project article
boost mailing list ideas

감사합니다,
Ovanes

3

AFAIK ASIO의 IOSTREAMS 동기 I/O 용입니다. 그러나 당신의 예제는 비동기 I/O를 사용하고자한다는 힌트를 준다. 다음은 비동기 I/O를 사용하여 요청에서 정수의 4 바이트 수가 선행되는 정수 배열로 구성된 요청을 읽는 서버의 작은 예입니다.int 치의 벡터에 성공 읽기, 서버 (4 바이트 응답 코드를 작성한다면 그래서 효과에 나는 = 1 수 (4 바이트) INT INT ... 등 로 integerss의 벡터를 직렬화하고) 다음 클라이언트에서 새 요청에 대한 읽기를 발행하십시오. 충분하다, 코드는 따른다.

#include <iostream> 
#include <vector> 
#include <boost/bind.hpp> 
#include <boost/function.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/thread.hpp> 
#include <boost/asio.hpp> 

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

class Connection 
{ 
public: 
    Connection(tcp::acceptor& acceptor) 
     : acceptor_(acceptor), socket_(acceptor.get_io_service(), tcp::v4()) 
    { 
    } 
    void start() 
    { 
     acceptor_.get_io_service().post(boost::bind(&Connection::start_accept, this)); 
    } 
private: 
    void start_accept() 
    { 
     acceptor_.async_accept(socket_,boost::bind(&Connection::handle_accept, this, 
      placeholders::error)); 
    } 
    void handle_accept(const boost::system::error_code& err) 
    { 
     if (err) 
     { 
      //Failed to accept the incoming connection. 
      disconnect(); 
     } 
     else 
     { 
      count_ = 0; 
      async_read(socket_, buffer(&count_, sizeof(count_)), 
       boost::bind(&Connection::handle_read_count, 
       this, placeholders::error, placeholders::bytes_transferred)); 
     } 
    } 
    void handle_read_count(const boost::system::error_code& err, std::size_t bytes_transferred) 
    { 
     if (err || (bytes_transferred != sizeof(count_)) 
     { 
      //Failed to read the element count. 
      disconnect(); 
     } 
     else 
     { 
      elements_.assign(count_, 0); 
      async_read(socket_, buffer(elements_), 
       boost::bind(&Connection::handle_read_elements, this, 
       placeholders::error, placeholders::bytes_transferred)); 
     } 
    } 

    void handle_read_elements(const boost::system::error_code& err, std::size_t bytes_transferred) 
    { 
     if (err || (bytes_transferred != count_ * sizeof(int))) 
     { 
      //Failed to read the request elements. 
      disconnect(); 
     } 
     else 
     { 
      response_ = 1; 
      async_write(socket_, buffer(&response_, sizeof(response_)), 
       boost::bind(&Connection::handle_write_response, this, 
       placeholders::error, placeholders::bytes_transferred)); 
     } 
    } 
    void handle_write_response(const boost::system::error_code& err, std::size_t bytes_transferred) 
    { 
     if (err) 
      disconnect(); 
     else 
     { 
      //Start a fresh read 
      count_ = 0; 
      async_read(socket_, buffer(&count_, sizeof(count_)), 
       boost::bind(&Connection::handle_read_count, 
       this, placeholders::error, placeholders::bytes_transferred)); 
     } 
    } 
    void disconnect() 
    { 
     socket_.shutdown(tcp::socket::shutdown_both); 
     socket_.close(); 
     socket_.open(tcp::v4()); 
     start_accept(); 
    } 
    tcp::acceptor& acceptor_; 
    tcp::socket socket_; 
    std::vector<int> elements_; 
    long count_; 
    long response_; 
}; 

class Server : private boost::noncopyable 
{ 
public: 
    Server(unsigned short port, unsigned short thread_pool_size, unsigned short conn_pool_size) 
     : acceptor_(io_service_, tcp::endpoint(tcp::v4(), port), true) 
    { 
     unsigned short i = 0; 
     for (i = 0; i < conn_pool_size; ++i) 
     { 
      ConnectionPtr conn(new Connection(acceptor_)); 
      conn->start(); 
      conn_pool_.push_back(conn); 
     } 

     // Start the pool of threads to run all of the io_services. 
     for (i = 0; i < thread_pool_size; ++i) 
     { 
      thread_pool_.create_thread(boost::bind(&io_service::run, &io_service_)); 
     } 
    } 
    ~Server() 
    { 
     io_service_.stop(); 
     thread_pool_.join_all(); 
    } 

private: 
    io_service io_service_; 
    tcp::acceptor acceptor_; 
    typedef boost::shared_ptr<Connection> ConnectionPtr; 
    std::vector<ConnectionPtr> conn_pool_; 
    boost::thread_group thread_pool_; 
}; 

boost::function0<void> console_ctrl_function; 

BOOL WINAPI console_ctrl_handler(DWORD ctrl_type) 
{ 
    switch (ctrl_type) 
    { 
    case CTRL_C_EVENT: 
    case CTRL_BREAK_EVENT: 
    case CTRL_CLOSE_EVENT: 
    case CTRL_SHUTDOWN_EVENT: 
    console_ctrl_function(); 
    return TRUE; 
    default: 
    return FALSE; 
    } 
} 

void stop_server(Server* pServer) 
{ 
    delete pServer; 
    pServer = NULL; 
} 

int main() 
{ 
    Server *pServer = new Server(10255, 4, 20); 
    console_ctrl_function = boost::bind(stop_server, pServer); 
    SetConsoleCtrlHandler(console_ctrl_handler, TRUE); 
    while(true) 
    { 
     Sleep(10000); 
    } 
} 
+0

이 코드 샘플 (누락 된 ')'이 수정 됨)은 컴파일되지만 실행시 예외가 발생했습니다. 시작할 때 즉시 handle_accept가 오류와 함께 호출되는 것 같습니다. 뭐가 문제 야? – Marius

+0

아,이 예제를 수정하려면'socket_'가'socket_ (acceptor.get_io_service())'처럼 초기화되어야합니다. 따라서'tcp :: v4()'만 제거하면된다. – Marius

관련 문제