boost.asioでTCP/UDP通信をしようと思うと、まずその辺のサンプルコードをとりあえず写経するでしょう。その際、送受信するバッファのためにasioの求めるバッファを使う事になるでしょう。しかも、UDPとTCPで別々のバッファを使う事になったり、asio::bufferだったりasio::streambufだったり、そこにboost::arrayを渡していたり・・・。
そこからデータを取ってくる時にもbuffer_castなる謎のキャストをかましたりするんじゃないでしょうか。普通にバイト列を受け取りor送りたいのに!とそのうち思ってくるでしょう、たぶん。私は思ったので解決策をメモしておきます。
解決策は簡単で、任意のバイト列へのポインタとサイズをboost::asio::bufferに渡してあげればいいです。
char byteArray[256]; auto buffer = boost::asio::buffer(byteArray, 256);
このbufferを受信/送信のそれぞれのメソッドの引数に与えてあげれば
//以下、boost::asio::を省略 io_service ios{ 2 }; ip::tcp::socket tcp{ios, ip::tcp::endpoint(ip::address::from_string("127.0.0.1"), 9876)) }; error_code error{}; //受信 read(tcp, buffer, transfer_exactly(256), error); //送信 write(tcp, buffer, error); //UDPなら ip::udp::socket udp{ios, ip::udp::endpoint(ip::address::from_string("127.0.0.1"), 9876) }; ip::udp::endpoint remote{}; //受信 udp.receive_from(buffer, remote, error); //送信 udp.send_to(buffer, remote, error);
のような感じで任意のバイト列(std::unique_ptr
他にも、boost::asio::bufferはstd::stringを受け取ることが出来、文字列を送る際はstd::stringを直接入れられます。また、PODタイプを格納したstd::vectorを受け取ることもできます。ちなみに、上のコードではcharの配列を渡す際に配列サイズをわざわざ書いていますが、PODタイプの配列を渡す分にはサイズ指定はなくてもいいです。
char byteArray[256]{}; auto buffer = boost::asio::buffer(byteArray); std::string str("abcdefg"); auto strbuf = boost::asio::buffer(str); std::vector<char> cvec = {0, 1, 2, 3, 4}; auto vecbuf = boost::asio::buffer(cvec);
各関数は同時にサイズを受け取ることもできて、あえて送信データの長さより短いサイズを指定してあげれば、データを途中まで転送することもできたりします。
※2018.5.29 bufferをクラスと勘違いしていた部分を修正・・・
参考文献
buffer - 1.67.0