2016-08-18 21 views
0

ASIOは、私のプロジェクトに最適な非同期クロスプラットフォームネットワーキングライブラリのようです。しかし、実際に接続するのが難しいです。スタンドアロンASIO非同期接続なし

まず、私はブーストを使用していません。私はWindows版を当面コンパイルしています。そのため、ASIOにC++ 11準拠のコンパイラを使用していることを通知するための定義を手動で追加する必要がありました。

Source.cpp

#define TCPCLIENT_DEBUG 
#include "TCPClient.hpp" 
#include <iostream> 

#define PORT "1234" 
#define HOST "127.0.0.1" 

int main() { 
    DEBUG("Starting program...\n"); 
    namespace ip = asio::ip; 

    asio::io_service io; 
    ip::tcp::resolver::query query(HOST, PORT); 
    ip::tcp::resolver resolver(io); 
    decltype(resolver)::iterator ep_iter = resolver.resolve(query); 

    TCPClient client(io, ep_iter); 

    try { 
     std::cin.get(); 
    } 
    catch (const std::exception &e) { // mainly to catch Ctrl+C 
     std::cout << e.what() << std::endl; 
    } 
    return 0; 
} 

TCPClient.hpp

#ifndef TCPCLIENT_HPP 
#define TCPCLIENT_HPP 

#include <functional> 

#if defined(_DEBUG) || defined(TCPCLIENT_DEBUG) 
#include <iostream> 
#define DEBUG(dbg_msg) std::cerr << dbg_msg 
#else 
#define DEBUG(dbg_msg) 
#endif 

#define ASIO_STANDALONE 
#define ASIO_HAS_CSTDINT 
#define ASIO_HAS_STD_ARRAY 
#define ASIO_HAS_STD_ADDRESSOF 
#define ASIO_HAS_STD_SHARED_PTR 
#define ASIO_HAS_STD_TYPE_TRAITS 

#include <asio.hpp> 
#ifndef BUFFER_SIZE 
#define BUFFER_SIZE 1024 
#endif 

class TCPClient { 
public: 
    TCPClient(asio::io_service& io, asio::ip::tcp::resolver::iterator endpoint_iter); 
    void on_connect(const asio::error_code& err); 

private: 
    asio::io_service& m_io;       // store the io service reference 
    asio::ip::tcp::socket m_sock;     // object's socket 
    static const size_t bufSize{ BUFFER_SIZE };  // default buffer size 
    char m_buffer[bufSize];       // store the received data in a buffer 
}; 

#endif//TCPCLIENT_HPP 

TCPClient.cpp

#include "TCPClient.hpp" 

TCPClient::TCPClient(asio::io_service& io, asio::ip::tcp::resolver::iterator endpoint_iter) : m_io{ io }, m_sock(io) { 
    asio::ip::tcp::endpoint endpoint = *endpoint_iter; 
    asio::error_code ec; 

    m_sock.async_connect(
     endpoint, 
     std::bind(
      &TCPClient::on_connect, 
      this, 
      std::placeholders::_1 
     ) 
    ); 
} 

void TCPClient::on_connect(const asio::error_code& err) { 
    DEBUG("Connected successfully!\n"); 
} 

on_connectが呼び出されないさんように私には思えます。 「Starting program ...」と表示されます。

のnetcatを使用して、私は、接続が成功して行く見ているリスナーを起動することができます。明らかに私のコードが間違っている何

enter image description here

?私は今のところ接続機能に取り組んでいるだけです。

+0

[Boost Asio connect \ _async never hander]の複製(http://stackoverflow.com/questions/22268914/boost-asio-connect-async-never-call-hander) –

答えて

2

async_connectを呼び出すことで、あなただけの非同期操作を登録します。非同期操作が実際に実行され、呼び出されるコールバックを取得するには、io_service.run()を明示的に呼び出す必要があります(std::cin.get()ではなくmain)。

asioはepollなどを使用しています。関心のあるイベント(自分のケースのソケット接続)を登録し、イベントが発生するのを待ちます。 io_service.run()はまさに待っているところです。

私はthis oneのように、いくつかのブースト:: ASIO asyncronousチュートリアルを見て、あなたをお勧めします。

2

ハンドラは、唯一、現在io_serviceを実行しているスレッド内で実行されています。 io_serviceは決して実行されないので、接続ハンドラは決して実行されません。これを解決するには、io_service::run()を呼び出すことによってio_serviceを実行します。

TCPClient client(io, ep_iter); 

try { 
    io.run(); 
} 
catch (const std::exception &e) { 
    std::cout << e.what() << std::endl; 
} 

Using a timer asynchronously Tutorialio_serviceを実行していることの重要性を指摘:

最後に、我々はio_serviceオブジェクト上io_service::run()メンバ関数を呼び出す必要があります。

ASIOライブラリーは、コールバックハンドラは、現在のみio_service::run()を呼び出しているスレッドから呼び出されるという保証を提供します。したがって、io_service::run()関数が呼び出されない限り、非同期待機完了のコールバックは呼び出されません。

io_service::run()機能も行うには、「仕事」はまだ存在している間に実行していきます。この例では、作業はタイマーの非同期待機であるため、タイマーが期限切れになりコールバックが完了するまで呼び出しは戻りません。

io_serviceには、io_service::run()を呼び出す前にいくつかの作業を行うことを覚えておくことが重要です。たとえば、上記の呼び出しをdeadline_timer::async_wait()にしなかった場合、io_serviceは何もする必要がないため、すぐにio_service::run()が返されます。

関連する問題