Skip to content

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: feature/body_m…

This branch is 25 commits behind master

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
include/boostconnect
sample
src
BoostConnect.sln
README.md

README.md

BoostConnect

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

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

必要なもの

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

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

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

使い方

使い方は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.