Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

so Easy Connect TCP/SSL/TLS by C++ with Boost.Asio

branch: master
README.md

BoostConnect

twit-libraryとかいう駄目駄目のOAuthライブラリの通信部分を分割し,リポジトリとして公開してみたものです.
それ以上でもそれ以下でもありません.

通信部分の安定化と汎用化を求めて設計されたBoostConnectは,
任意のポート・アドレスに接続する事ができるクライアントと,
任意のHTTPサーバを立てることが出来るサーバーを提供しています.
(本当はもっと機能を増やしたかったりしますが)

このライブラリはライブラリとして使用(事前に.aや.libを作成)する方法と,ヘッダーのincludeのみで使用する方法が選べます.
それぞれの方法については「ライブラリとして使用」・「ヘッダーとして利用」の項を参照してください.
ただしどちらを選んだ場合でも,同じ機能を利用することができます.しかし,ヘッダーとして利用する場合は毎回のコンパイル時間がめちゃくちゃ長くなります.

必要なもの

  • Boost C++ Library: 大部分はこのライブラリに依存しています.ビルドしてパスを通して置いてください.

  • OpenSSL SSL/TLS拡張を行う場合のみ,パスを通しておいてください.
    #define USE_SSL_BOOSTCONNECTによってSSLが有効になります.

SSL通信をしない場合はOpenSSLは必要ありません!

ライブラリとして使用

生のままBoostConnectを使用すると,毎回のようにコンパイル時間が長くなり,大変なのです.
そこで.a(Windowsでは.lib)としてlibrary化することができるようにしました.

Windowsの場合はBoostConnect.slnに存在しているboostconnectプロジェクトのインクルードパス・ライブラリパスを適宜変更の上,コンパイルさせてください.
Linuxの場合はmakeを叩くだけで行けます(多分

どちらでビルドしてもlibディレクトリ下にlibboostconnect.*というライブラリができますので,利用する際にこれをリンクしてください.

ヘッダーとして利用

ヘッダーのincludeを行う前に#define BOOSTCONNECT_LIB_BUILDを書いてください.
これだけでOKです.

使い方

使い方はsample.cppを見ると解りやすいかも知れません.

簡単に説明すると,

  • bstcon::clientがクライアント
  • bstcon::serverがサーバー 用のクラスです.

どちらもコンストラクタでboost::asio::io_serviceを渡します.
この時,第二引数にboost::asio::ssl::contextを渡すと暗黙的にSSL通信を行うことになります.

サンプルの詳細な説明は以下に提示しますから,見るとわかるかも知れません.
サンプルはVC10以降の場合は付属の.sln,gccの場合はg++ -std=c++11 ./sample/sample.cpp -I./include/ -lssl -lcrypto -lboost_thread -lboost_systemでコンパイルできるはずです. clang++もclang++ -std=c++11 ./sample/sample.cpp -I./include/ -lssl -lcrypto -lboost_thread -lboost_systemで出来ましたよっ

クライアント

クライアントとしての使い方は以下のとおりです.
それぞれのサンプルのコメントを全て外すと,SSL通信が確立します.
SSL通信を行う場合は全ての#includeの前に,#define USE_SSL_BOOSTCONNECTを宣言してください.

  • 共通部品

    boost::asio::io_service io_service;
    // boost::asio::ssl::context ctx(io_service,boost::asio::ssl::context_base::sslv3_client);
    boost::shared_ptr<boost::asio::streambuf> request_buf(new boost::asio::streambuf());
    {
     std::ostream os(request_buf.get());
      os << "GET / HTTP/1.1\r\n";
      os << "Host: "+host+"\r\n";
      os << "Connection: close\r\n";
      os << "\r\n";
    }
    
  • 同期通信

    bstcon::client c(
      io_service,
      // ctx,
      bstcon::connection_type::sync
      );
    
    bstcon::client::connection_ptr connection = c("google.co.jp",[](bstcon::client::connection_ptr,boost::system::error_code){});
    boost::shared_ptr<bstcon::response> response = connection->send(request_local);
    
    std::cout << "Status Code: " << response->status_code << " " << response->status_message << std::endl;
    std::cout << response->body + "\n\n" <<std::endl;
    
  • 非同期通信

    bstcon::client c(
      io_service,
      // ctx,
      bstcon::connection_type::async
      );
    
    bstcon::client::connection_ptr connection = c(
        "google.co.jp",
        [&connection](bstcon::client::connection_ptr handled_connection, boost::system::error_code ec)->void
        {           
            //ソケットのコネクションが終わったらここに来る
            assert(connection == handled_connection);
            connection->send(
                request_buf,
                [](bstcon::client::response_type response, boost::system::error_code ec)
                {
                    //レスポンス受け取り完了
                    if(!!ec) return;
    
                    std::cout << "Status Code: " << response->status_code << " " << response->status_message << std::endl;
                    std::cout << response->body + "\n\n" <<std::endl;
                }
            );
        }
    );
    
    io_service.run();
    

同期通信は簡単.clientの第2引数は削除できるようにする方針. 非同期通信の方はio_service.run();があるのが特徴.あと,ラムダがネストしまくってるけど一つ一つ関数にすれば綺麗だと思うし, sendのコールバックでレスポンスを受け取った後,connection->sendすればまた新しいのをそのまま始められるよ. なるべくライブラリのユーザが使いやすいように,ポインタとかで同じように扱えるようになってる.

サーバー

サーバーとしての使用は今のところHTTP通信としてのみです.
ただHTTP通信のボディにデータを載せてやりとりするチャット(あるのかな?)とかには使用できるかも知れません.

boost::asio::io_service io_service;
// boost::asio::ssl::context ctx(io_service,boost::asio::ssl::context_base::sslv3_client);

// ctxの設定(ctx Setting)

bstcon::server service(io_service,ctx,5600);
service.start(
  [](const request_type& req,response_type& res)
  {
    res.status_code = 200;
    res.http_version = "1.1";
    res.status_message = "OK";
    res.body = "<html><body>Test Response</body></html>";
    res.header["Content-Length"] = (boost::format("%d") % res.body.size()).str();
  }
);

上のコードでは常にTest Responseと表示するレスポンスを返します.
どんなパスにリクエストが来ても同じ物を返すだけの例.
req.uriのパスに応じたローカルファイルの内容をres.bodyに流し込めば簡単なHTTPサーバーとしても動きます.

"namespace bstcon"について

由来は BoostConnect -> BstConnect -> BstCon -> bstcon です.
namespaceなどは,なんとなく即席で決めたので,何か既存のライブラリとの衝突などがあれば,リクエストをください.多分対処します.

Something went wrong with that request. Please try again.