UTF-16と仮定したCStringWをUTF-8のCStringAに変換してからシリアライズしています。
まずシリアライズ部分。
cstring_serialization.hpp
#ifndef MFC_CSTRING_SERIALiZATION_INCLUDE #define MFC_CSTRING_SERIALiZATION_INCLUDE /*============================================================================= Copyright (C) Akira Takahashi 2011 Copyright (c) John Paul Pirau 2008 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) UTF16toUTF8() and UTF8toUTF16() function published here: http://www.codeproject.com/KB/string/utfConvert.aspx ==============================================================================*/ #include <afx.h> #include <string> #include <boost/serialization/serialization.hpp> #include <boost/serialization/string.hpp> namespace mfc_code_conv { CStringA UTF16toUTF8(const CStringW& utf16) { CStringA utf8; int len = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, 0, 0); if (len>1) { char *ptr = utf8.GetBuffer(len-1); if (ptr) WideCharToMultiByte(CP_UTF8, 0, utf16, -1, ptr, len, 0, 0); utf8.ReleaseBuffer(); } return utf8; } CStringW UTF8toUTF16(const CStringA& utf8) { CStringW utf16; int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0); if (len>1) { wchar_t *ptr = utf16.GetBuffer(len-1); if (ptr) MultiByteToWideChar(CP_UTF8, 0, utf8, -1, ptr, len); utf16.ReleaseBuffer(); } return utf16; } } // namespace mfc_code_conv namespace boost { namespace serialization { template <class Archive> inline void save(Archive& ar, const CStringW& s, const unsigned int version) { static_cast<void>(version); const CStringA utf8 = ::mfc_code_conv::UTF16toUTF8(s); const std::string ss(utf8); ar & boost::serialization::make_nvp("String", ss); } template<class Archive> inline void load(Archive& ar, CStringW& s, const unsigned int version) { static_cast<void>(version); std::string ss; ar & boost::serialization::make_nvp("String", ss); const CStringA utf8 = ss.c_str(); s = ::mfc_code_conv::UTF8toUTF16(utf8); } template <class Archive> inline void serialize(Archive& ar, CStringW& s, const unsigned int version) { boost::serialization::split_free(ar, s, version); } }} // namespace boost::serialization #endif // MFC_CSTRING_SERIALiZATION_INCLUDE
クライアント(送る側)
#include "cstring_serialization.hpp" #include <boost/serialization/serialization.hpp> #include <boost/serialization/nvp.hpp> #include <boost/archive/xml_oarchive.hpp> #include <boost/bind.hpp> #include <boost/asio.hpp> namespace asio = boost::asio; namespace ip = asio::ip; struct Data { int value; CStringW str; private: friend class boost::serialization::access; template <class Archive> void serialize(Archive& ar, unsigned int version) { static_cast<void>(version); ar & boost::serialization::make_nvp("value", value); ar & boost::serialization::make_nvp("str", str); } }; class Client { asio::io_service& io_service_; ip::tcp::socket socket_; std::string send_data_; public: Client(asio::io_service& io_service) : io_service_(io_service), socket_(io_service) {} void connect() { socket_.connect(ip::tcp::endpoint(ip::address::from_string("127.0.0.1"), 31400)); } void send(const Data& data) { std::ostringstream ss; boost::archive::xml_oarchive ar(ss); ar << boost::serialization::make_nvp("data", data); send_data_ = ss.str(); asio::async_write(socket_, asio::buffer(send_data_), boost::bind(&Client::on_send_end, this, asio::placeholders::error)); } void on_send_end(const boost::system::error_code& error) { if (error) { std::cout << error.message() << std::endl; } else { std::cout << "送信成功" << std::endl; } } }; int main() { asio::io_service io_service; Client client(io_service); client.connect(); Data data; data.value = 3; data.str = L"abcあいうえおxyz"; client.send(data); io_service.run(); }
サーバー側(受け取る側)
#include <afxwin.h> #include "cstring_serialization.hpp" #include <boost/serialization/serialization.hpp> #include <boost/serialization/string.hpp> #include <boost/serialization/nvp.hpp> #include <boost/archive/xml_iarchive.hpp> #include <boost/bind.hpp> #include <boost/asio.hpp> namespace asio = boost::asio; namespace ip = asio::ip; struct Data { int value; CString str; private: friend class boost::serialization::access; template <class Archive> void serialize(Archive& ar, unsigned int version) { static_cast<void>(version); ar & boost::serialization::make_nvp("value", value); ar & boost::serialization::make_nvp("str", str); } }; class Server { asio::io_service& io_service_; ip::tcp::socket socket_; asio::streambuf receive_buff_; std::string receive_data_; boost::function<void(const boost::system::error_code&, const Data&)> receive_handler; public: Server(asio::io_service& io_service) : io_service_(io_service), socket_(io_service) {} void accept() { ip::tcp::acceptor acc(io_service_, ip::tcp::endpoint(ip::tcp::v4(), 31400)); acc.accept(socket_); } void receive(boost::function<void(const boost::system::error_code&, const Data&)> handler) { receive_handler = handler; // Start reading remaining data until EOF. boost::asio::async_read(socket_, receive_buff_, boost::asio::transfer_at_least(1), boost::bind(&Server::handle_read_content, this, boost::asio::placeholders::error)); } void handle_read_content(const boost::system::error_code& error) { if (!error) { receive_data_ += asio::buffer_cast<const char*>(receive_buff_.data()); // Continue reading remaining data until EOF. boost::asio::async_read(socket_, receive_buff_, boost::asio::transfer_at_least(1), boost::bind(&Server::handle_read_content, this, boost::asio::placeholders::error)); } else if (error != boost::asio::error::eof) { receive_handler(error, Data()); } else { std::stringstream ss; ss << receive_data_; boost::archive::xml_iarchive ar(ss); Data data; ar >> boost::serialization::make_nvp("data", data); receive_handler(boost::system::error_code(), data); } } }; void received_data(const boost::system::error_code& error, const Data& data) { if (error) { std::cout << "Error: " << error.message() << std::endl; } else { std::cout << data.value << std::endl; AfxMessageBox(data.str); } } int main() { asio::io_service io_service; Server server(io_service); server.accept(); server.receive(received_data); io_service.run(); }