Boost 라이브러리는 1.53 버전부터 코루틴이 정식으로 포함되었다. Boost 라이브러리 1.54 버전의 Asio에서는 코루틴을 Asio에서도 사용할 수 있게 되었다.

Asio에서 코루틴을 사용하기 위해서는 boost:asio::spawn을 사용한다.

 

Asio에서 비동기 I/O 함수를 사용할 때는 언제나 Asio의 비동기 함수를 호출하고, 이때 완료 함수를 등록 한다. 그리고 완료 함수가 호출에 의해 작업의 완료를 알게 된다.



boost::asio::spawn을 사용하면 코루틴에 의해 비동기 함수를 호출하면 호출한 곳으로 제어권을 넘긴 후 비동기 작업이 완료하면 비동기 함수 호출 이후 부분에 복귀하여 남은 작업을 처리한다.

아래는 boost::asio::spawn을 사용하여 비동기로 데이터를 보내는 코드이다.


 


< boost::asio::spawn을 사용하여 비동기로 데이터 보내기 >

 

코루틴을 사용해본 경험이 없다면 아마 위의 코드만으로는 잘 이해가 안될 것이다. 그러니 기존의 Chatting 서버를 boost::asio::spawn 사용 버전으로 만든 'ChattingTCPServer_spawn' 프로젝트를 꼭 보고 실행까지 해보기 바란다. boost::asio::spawn을 사용해서 코드가 이전에 비해서 줄어들어서 어렵지 않게 이해할 수 있을 것이다.


ChattingTCPServer_spawn.zip


 

 

<참조>

코루틴(coroutine) 관련 자료

http://devnote.tistory.com/223

 

Boost 라이브러리의 코루틴에 관한 글

C++에서도 coroutine & yield  http://gamedevforever.com/209

다시 한번 C++에서도 coroutin   http://www.gamedevforever.com/289

</참조>

 

<참조>

Boost 라이브러리의 asio::spawn 관련 예제 코드

http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/example/cpp11/spawn/

</참조>

 

by 흥배 2014. 7. 7. 08:00

packaged_task를 사용하면 병렬 프로그래밍 패턴의 task 패턴과 같이 Asio에서 백그라운드 작업을 처리할 수 있다.





< ioservice.post packaged_task 사용하기 >

 

완전한 코드는 'io_service_post_packaged_task' 프로젝트를 참조하기 바란다.


io_service_post_packaged_task.zip


 

by 흥배 2014. 7. 3. 08:00

future를 사용하면 비동기 IO 처리의 결과 값을 얻을 수 있다.

아래의 코드는 future를 사용하여 UDP로 보내기와 받기를 하고 있다. future를 사용하고 있어서 비동기 완료 함수를 지정하지 않아도 된다.




( 완전한 코드는 'AsynchronousUDPClient_future' 프로젝트에 있다. )


AsynchronousUDPClient_future.zip


by 흥배 2014. 6. 30. 08:00

지금의 C++ 표준은 03 이 아닌 C++11 이다. 새로운 시대에 맞게 Asio 프로그래밍을 할 때 C++11 표준을 사용하는 것이 좋다.

 

C++03 표준을 사용하여 Asio를 사용할 때는 AsioAccept, Send, Receive 등의 비동기 함수에 완료 함수를 등록할 때 boost::bind를 사용하였지만 C++11 에서는 lambda를 사용한다.

 

Asio에서 리모트의 접속을 받아들이는 함수 async_accept C++03에서는 아래와 같은 방식으로사용했다.

 

boost::asio::ip::tcp::acceptor m_acceptor;

 

void handle_accept(Session* pSession, const boost::system::error_code& error)

{

if (!error)

{     

       std::cout << "클라이언트 접속 성공" << std::endl;

                   

       pSession->PostReceive();

}

}

 

m_acceptor.async_accept( m_pSession->Socket(),

                    boost::bind(&TCP_Server::handle_accept,

                           this,

                           m_pSession,

                           boost::asio::placeholders::error)

                    );

 

위의 코드를 C++11 방식으로 바꾸면 아래와 같다.

m_acceptor.async_accept( m_pSession->Socket(),

                     [this](boost::system::error_code error)

                    {

                       if (!error)

                       {  

                          std::cout << "클라이언트 접속 성공" << std::endl;

                          m_pSession->PostReceive();

                       }

                      

                       StartAccept();

                    }

                    );

 

 

 

by 흥배 2013. 8. 12. 08:00
  • iruis 2013.08.16 18:25 신고 ADDR EDIT/DEL REPLY

    저도 C++11 셈플을 보고 Visual Studio 2012로 코드를 옮겨봤는데... 컴파일 에러 나더군요. std::move에서 에러가 나던데 gcc에서 빌드하면 잘 되는 것을 보면 둘 중 하나의 버그, 또는 컴파일러가 아직 C++11 지원이 완전하지 않은것으로 보입니다.

    예제를 그대로 하지 않고 람다를 쓴것만 코드를 사용하는 것으로 변형 한다면 되긴 하겠지만... 예제를 보며 VS 2012로 코딩하기 좀 무리가 있더군요.

    그래도 bind 대신 람다를 쓸 수 있는건 매우 편리해졌다고 생각합니다.

    • 흥배 2013.08.17 20:42 신고 EDIT/DEL

      참고로 위 코드는 제가 VS 2012에서 컴파일 한 코드인데 lambda 지원에 문제가 없는 걸로 알고 있습니다

  • GameP 2014.03.10 08:43 신고 ADDR EDIT/DEL REPLY

    안녕하세요. 한가지 궁금한점이 있는데..

    lamda 로 변경하기전에는 boost::asio::placeholders::error) 를 사용하는데.. lamda 로 변경한후에는

    boost::system::error_code error 를 사용하는 이유가 무엇인가요?

    • 흥배 2014.03.10 12:57 신고 EDIT/DEL

      boost::asio::placeholders::error는 bind 함수를 사용하기 위해서 사용했는데 람다에서는 bind 함수를 사용하지 않기 때문입니다

근래 gcc나 Clang 등이 C++11 지원을 완료함에 따라서 기존에 C++03 방식으로 만들었던 C++ 프로그램에 조금씩 C++11 방식이 적용되고 있다.


얼마전에 Boost 라이브러리가 1.54 버전이 나왔는데 Asio 예제 코드를 03과 11 버전 두 가지로 나누어서 제공하고 있다.


http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/examples.html





http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/examples/cpp11_examples.html



이제 03 방식의 관습에서 벗어나서 C++11 방식으로 의식하면서 사용해야 할 것 같다



by 흥배 2013. 7. 11. 08:00

자기 자신(컴퓨터)의 IP 어드레스는 다음과 같은 방법으로 얻을 수 있습니다.


처음에는 IPv6 주소, 두 번째는 IPv4 주소가 나옵니다.


std::cout << "1" << std::endl; boost::asio::io_service io_service; boost::asio::ip::tcp::resolver resolver(io_service); boost::asio::ip::tcp::resolver::query query(boost::asio::ip::host_name(), ""); boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query); boost::asio::ip::tcp::resolver::iterator end; // End marker. while (iter != end) { boost::asio::ip::tcp::endpoint ep = *iter++; std::cout << ep << std::endl; } { std::cout << "2" << std::endl; boost::asio::ip::tcp::resolver resolver(io_service);

boost::asio::ip::tcp::resolver::query query(boost::asio::ip::host_name(),""); boost::asio::ip::tcp::resolver::iterator it=resolver.resolve(query); while(it!=boost::asio::ip::tcp::resolver::iterator()) { boost::asio::ip::address addr=(it++)->endpoint().address(); if(addr.is_v6()) { std::cout<<"ipv6 address: "; } else std::cout<<"ipv4 address: "; std::cout<<addr.to_string()<<std::endl; } }





by 흥배 2013. 7. 4. 08:00
| 1 |