2017-01-24 12 views
0

私はhttp://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/example/serialization/connection.hppの例に従っています。 ...私はaynchronous_readと呼ばれる、より業務に挿入するためにconnection.hppヘッダーを変更したとasynchronous_write.Theコードがここに装着されている を使ってBOOST ASIOバッファー

// 
// connection.hpp 
// ~~~~~~~~~~~~~~ 
// 
// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) 
// 
// 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) 
// 

#ifndef SERIALIZATION_CONNECTION_HPP 
#define SERIALIZATION_CONNECTION_HPP 

#include <boost/asio.hpp> 
#include <boost/archive/text_iarchive.hpp> 
#include <boost/archive/text_oarchive.hpp> 
#include <boost/bind.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/tuple/tuple.hpp> 
#include <iomanip> 
#include <string> 
#include <sstream> 
#include <vector> 

namespace s11n_example { 

/// The connection class provides serialization primitives on top of a socket. 
/** 
* Each message sent using this class consists of: 
* @li An 8-byte header containing the length of the serialized data in 
* hexadecimal. 
* @li The serialized data. 
*/ 
class connection 
{ 
public: 
    /// Constructor. 
    connection(boost::asio::io_service& io_service) 
    : socket_(io_service) 
    { 
    } 

    /// Get the underlying socket. Used for making a connection or for accepting 
    /// an incoming connection. 
    boost::asio::ip::tcp::socket& socket() 
    { 
    return socket_; 
    } 

    /// Asynchronously write a data structure to the socket. 
    template <typename T, typename Handler> 
    void async_write(const T& t, Handler handler) 
    { 
    // Serialize the data first so we know how large it is. 
    std::ostringstream archive_stream; 
    boost::archive::text_oarchive archive(archive_stream); 
    archive << t; 
    outbound_data_ = archive_stream.str(); 

    // Format the header. 
    std::ostringstream header_stream; 
    header_stream << std::setw(header_length) 
     << std::hex << outbound_data_.size(); 
    if (!header_stream || header_stream.str().size() != header_length) 
    { 
     // Something went wrong, inform the caller. 
     boost::system::error_code error(boost::asio::error::invalid_argument); 
     socket_.get_io_service().post(boost::bind(handler, error)); 
     return; 
    } 
    outbound_header_ = header_stream.str(); 

    // Write the serialized data to the socket. We use "gather-write" to send 
    // both the header and the data in a single write operation. 
    std::vector<boost::asio::const_buffer> buffers; 
    buffers.push_back(boost::asio::buffer(outbound_header_)); 
    buffers.push_back(boost::asio::buffer(outbound_data_)); 
    boost::asio::async_write(socket_, buffers, handler); 
    } 

    ///Asynchronously write a string to the socket. 
    template <typename T, typename Handler> 
    void asyncronous_write(const T& t, Handler handler) 
    { 
    std::ostringstream archive_stream; 
    boost::archive::text_oarchive archive(archive_stream); 
    archive << t; 
    outbound_str_ = archive_stream.str(); 
    //boost::asio::buffer buffer1(outbound_str_); 
    boost::asio::async_write(socket_,boost::asio::buffer(outbound_str_), handler); 
    } 
    /// Asynchronously read a string from the socket. 
    template <typename T, typename Handler> 
    void asyncronous_read(T& t, Handler handler) 
    { 
    // Issue a read operation to read exactly the number of bytes in a header. 
    void (connection::*f)(
     const boost::system::error_code&, 
     T&, boost::tuple<Handler>) 
     = &connection::handle_read_str<T, Handler>; 
    boost::asio::async_read(socket_, boost::asio::buffer(inbound_str_), 
     boost::bind(f, 
      this, boost::asio::placeholders::error, boost::ref(t), 
      boost::make_tuple(handler))); 
    } 

    /// Handle a completed read of message data. 
    template <typename T, typename Handler> 
    void handle_read_str(const boost::system::error_code& e, 
     T& t, boost::tuple<Handler> handler) 
    { 
    if (e) 
    { 
     boost::get<0>(handler)(e); 
    } 
    else 
    { 
     // Extract the data structure from the data just received. 
     try 
     { 
     std::string archive_data(&inbound_str_[0], inbound_str_.size()); 
     std::istringstream archive_stream(archive_data); 
     boost::archive::text_iarchive archive(archive_stream); 
     archive >> t; 
     } 
     catch (std::exception& e) 
     { 
     // Unable to decode data. 
     boost::system::error_code error(boost::asio::error::invalid_argument); 
     boost::get<0>(handler)(error); 
     return; 
     } 

     // Inform caller that data has been received ok. 
     boost::get<0>(handler)(e); 
    } 
    } 



    /// Asynchronously read a data structure from the socket. 
    template <typename T, typename Handler> 
    void async_read(T& t, Handler handler) 
    { 
    // Issue a read operation to read exactly the number of bytes in a header. 
    void (connection::*f)(
     const boost::system::error_code&, 
     T&, boost::tuple<Handler>) 
     = &connection::handle_read_header<T, Handler>; 
    boost::asio::async_read(socket_, boost::asio::buffer(inbound_header_), 
     boost::bind(f, 
      this, boost::asio::placeholders::error, boost::ref(t), 
      boost::make_tuple(handler))); 
    } 

    /// Handle a completed read of a message header. The handler is passed using 
    /// a tuple since boost::bind seems to have trouble binding a function object 
    /// created using boost::bind as a parameter. 
    template <typename T, typename Handler> 
    void handle_read_header(const boost::system::error_code& e, 
     T& t, boost::tuple<Handler> handler) 
    { 
    if (e) 
    { 
     boost::get<0>(handler)(e); 
    } 
    else 
    { 
     // Determine the length of the serialized data. 
     std::istringstream is(std::string(inbound_header_, header_length)); 
     std::size_t inbound_data_size = 0; 
     if (!(is >> std::hex >> inbound_data_size)) 
     { 
     // Header doesn't seem to be valid. Inform the caller. 
     boost::system::error_code error(boost::asio::error::invalid_argument); 
     boost::get<0>(handler)(error); 
     return; 
     } 

     // Start an asynchronous call to receive the data. 
     inbound_data_.resize(inbound_data_size); 
     void (connection::*f)(
      const boost::system::error_code&, 
      T&, boost::tuple<Handler>) 
     = &connection::handle_read_data<T, Handler>; 
     boost::asio::async_read(socket_, boost::asio::buffer(inbound_data_), 
     boost::bind(f, this, 
      boost::asio::placeholders::error, boost::ref(t), handler)); 
    } 
    } 

    /// Handle a completed read of message data. 
    template <typename T, typename Handler> 
    void handle_read_data(const boost::system::error_code& e, 
     T& t, boost::tuple<Handler> handler) 
    { 
    if (e) 
    { 
     boost::get<0>(handler)(e); 
    } 
    else 
    { 
     // Extract the data structure from the data just received. 
     try 
     { 
     std::string archive_data(&inbound_data_[0], inbound_data_.size()); 
     std::istringstream archive_stream(archive_data); 
     boost::archive::text_iarchive archive(archive_stream); 
     archive >> t; 
     } 
     catch (std::exception& e) 
     { 
     // Unable to decode data. 
     boost::system::error_code error(boost::asio::error::invalid_argument); 
     boost::get<0>(handler)(error); 
     return; 
     } 

     // Inform caller that data has been received ok. 
     boost::get<0>(handler)(e); 
    } 
    } 

private: 
    /// The underlying socket. 
    boost::asio::ip::tcp::socket socket_; 

    /// The size of a fixed length header. 
    enum { header_length = 8 }; 

    /// Holds an outbound header. 
    std::string outbound_header_; 

    /// Holds the outbound data. 
    std::string outbound_data_; 
    std::string outbound_str_; 

    /// Holds an inbound header. 
    char inbound_header_[header_length]; 

    /// Holds the inbound data. 
    std::vector<char> inbound_data_; 
    std::vector<char>inbound_str_; 
    //char* inbound_str_=new char[1024]; 
}; 

typedef boost::shared_ptr<connection> connection_ptr; 

} // namespace s11n_example 

#endif // SERIALIZATION_CONNECTION_HPP 

サーバーとクライアントのコードがある

---

#include <boost/asio.hpp> 
#include <boost/bind.hpp> 
#include <boost/lexical_cast.hpp> 
#include <iostream> 
#include <fstream> 
#include <vector> 
#include "connection.hpp" // Must come before boost/serialization headers. 
#include <boost/serialization/vector.hpp> 
#include "structsample.hpp" 


namespace s11n_example { 

/// Serves stock quote information to any client that connects to it. 
class server 
{ 
public: 
    /// Constructor opens the acceptor and starts waiting for the first incoming 
    /// connection. 

    server(boost::asio::io_service& io_service, unsigned short port) 
    : acceptor_(io_service, 
     boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) 
    { 
    // Create the data to be sent to each client. 
    std::string str; 
    std::ifstream in; 
    stock s; 
    in.open("aces.clf"); 
    if(!in) 
    { 
    std::cout<<"Error in Opening a file"<<std::endl; 
    exit(1); 
    } 
    for(int i=0;i<13;i++) 
    { 
     getline(in,str); 
    } 
    while(!in.eof()) 
    { 
     getline(in,str); 
     s.data.append(str); 
     getline(in,str); 
     s.data.append(str); 
     s.d_size=s.data.size(); 
     stocks_.push_back(s); 
     s.data.clear(); 
    } 

    // Start an accept operation for a new connection. 
    connection_ptr new_conn(new connection(acceptor_.get_io_service())); 
    acceptor_.async_accept(new_conn->socket(), 
     boost::bind(&server::handle_accept, this, 
      boost::asio::placeholders::error, new_conn)); 
    } 

    /// Handle completion of a accept operation. 
    void handle_accept(const boost::system::error_code& e, connection_ptr conn) 
    { 
    std::string buf1; 
    if (!e) 
    { 

     // Successfully accepted a new connection. Send the list of stocks to the 
     // client. The connection::async_write() function will automatically 
     // serialize the data structure for us. 
    for(int i=0;i<5;i++) 
    { 

     conn->async_write(stocks_[i], 
      boost::bind(&server::handle_write, this, 
      boost::asio::placeholders::error, conn)); 

     usleep(500000); 
     conn->async_read(buf1, 
      boost::bind(&server::handle_read, this, 
      boost::asio::placeholders::error, conn)); 
     std::cout<<buf1<<"\n"<<std::endl; 
    } 

     // Start an accept operation for a new connection. 
     connection_ptr new_conn(new connection(acceptor_.get_io_service())); 
     acceptor_.async_accept(new_conn->socket(), 
      boost::bind(&server::handle_accept, this, 
      boost::asio::placeholders::error, new_conn)); 
    } 
    else 
    { 
     // An error occurred. Log it and return. Since we are not starting a new 
     // accept operation the io_service will run out of work to do and the 
     // server will exit. 
     std::cerr << e.message() << std::endl; 
    } 
    } 

    /// Handle completion of a write operation. 
    void handle_write(const boost::system::error_code& e, connection_ptr conn) 
    { 

     //conn->async_read(buf1, 
      //boost::bind(&server::handle_read, this, 
      // boost::asio::placeholders::error, conn)); 
    // std::cout<<buf1<<"\n"<<std::endl; 

    } 

///handle completion of read operation. 
void handle_read(const boost::system::error_code& e,connection_ptr conn) 
{ 
//if(!e) 
    //{ 
      //std::cout<<"\n"<<stocks_1.data<<std::endl; 
      //stocks_1.data.clear(); 
    //} 
     //{ 
      //if (buf1.compare("data received and processed")==0) 
      //{ 
          // buf1.clear(); 
          //std::cout<<buf1<<"\n"<<std::endl; 

      //} 
      //else 
      //{ 
       //std::cout<<"Error occurred"<<std::endl; 
       //exit(1); 
      // } 
    //} 
} 

private: 
    /// The acceptor object used to accept incoming socket connections. 
    boost::asio::ip::tcp::acceptor acceptor_; 

    /// The data to be sent to each client. 
    std::vector<stock> stocks_; 
}; 

} // namespace s11n_example 

int main(int argc, char* argv[]) 
{ 
    try 
    { 
    // Check command line arguments. 
    if (argc != 2) 
    { 
     std::cerr << "Usage: server <port>" << std::endl; 
     return 1; 
    } 
    unsigned short port = boost::lexical_cast<unsigned short>(argv[1]); 
    boost::asio::io_service io_service; 
    s11n_example::server server(io_service, port); 
    io_service.run(); 
    } 
    catch (std::exception& e) 
    { 
    std::cerr << e.what() << std::endl; 
    } 

    return 0; 
} 






#include <boost/asio.hpp> 
#include <boost/bind.hpp> 
#include <iostream> 
#include <fstream> 
#include <vector> 
#include "connection.hpp" // Must come before boost/serialization headers. 
#include <boost/serialization/vector.hpp> 
#include "structsample.hpp" 

struct stock1 
    { 
    std::string data; 
    int d_size; 
    template <typename Archive> 
    void serialize(Archive& ar, const unsigned int version) 
    { 
    ar & data; 
    ar & d_size; 

    } 
} stocks_1; 
namespace s11n_example { 

/// Downloads stock quote information from a server. 
class client 
{ 
public: 
    /// Constructor starts the asynchronous connect operation. 
    client(boost::asio::io_service& io_service, 
     const std::string& host, const std::string& service) 
    : connection_(io_service) 
    { 
    // Resolve the host name into an IP address. 
    boost::asio::ip::tcp::resolver resolver(io_service); 
    boost::asio::ip::tcp::resolver::query query(host, service); 
    boost::asio::ip::tcp::resolver::iterator endpoint_iterator = 
     resolver.resolve(query); 
    boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; 

// Start an asynchronous connect operation. 
    connection_.socket().async_connect(endpoint, 
     boost::bind(&client::handle_connect, this, 
      boost::asio::placeholders::error, ++endpoint_iterator)); 
    } 

    /// Handle completion of a connect operation. 
    void handle_connect(const boost::system::error_code& e, 
     boost::asio::ip::tcp::resolver::iterator endpoint_iterator) 
    { 
    if (!e) 
    { 
     // Successfully established connection. Start operation to read the list 
     // of stocks. The connection::async_read() function will automatically 
     // decode the data that is read from the underlying socket. 
     connection_.async_read(stocks_1, 
      boost::bind(&client::handle_read, this, 
      boost::asio::placeholders::error)); 

    } 
    else if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator()) 
    { 
     // Try the next endpoint. 
     connection_.socket().close(); 
     boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; 
     connection_.socket().async_connect(endpoint, 
      boost::bind(&client::handle_connect, this, 
      boost::asio::placeholders::error, ++endpoint_iterator)); 
    } 

else 
    { 
     // An error occurred. Log it and return. Since we are not starting a new 
     // operation the io_service will run out of work to do and the client will 
     // exit. 
     std::cerr << e.message() << std::endl; 
    } 
    } 

    /// Handle completion of a read operation. 
    void handle_read(const boost::system::error_code& e) 
    { 
    std::string buf2; 
    if (!e) 
    { 

     std::cout << " data: " << stocks_1.data << "\n"; 
     std::cout << " size: " << stocks_1.d_size << "\n"; 

     usleep(500000); 
     if(!e) 
     { 
     //stocks_1.data="data received and processed"; 
     //tocks_1.d_size=stocks_1.data.size(); 
     connection_.async_write(buf2, 
      boost::bind(&client::handle_write, this, 
      boost::asio::placeholders::error)); 
     std::cout<<buf2<<std::endl; 
     //buf2.clear(); 
     // connection_.async_write(stocks_1, 
      //boost::bind(&client::handle_write, this, 
      //boost::asio::placeholders::error)); 
     //stocks_1.data.clear(); 
     } 
    } 
     else 
    { 
     // An error occurred. 
     std::cerr << e.message() << std::endl; 
    } 


// Since we are not starting a new operation the io_service will run out of 
    // work to do and the client will exit. 

    } 

void handle_write(const boost::system::error_code& e) 
{ 
    if(!e) 
{ 
      connection_.async_read(stocks_1, 
      boost::bind(&client::handle_read, this, 
      boost::asio::placeholders::error)); 
} 
else 
    //std::cout<<"Error is there"<<std::endl; 
     exit(1); 
} 
private: 
    /// The connection to the server. 
    connection connection_; 

    /// The data received from the server. 
    std::vector<stock> stocks_; 


}; 

} // namespace s11n_example 

int main(int argc, char* argv[]) 
{ 
    try 
    { 
    // Check command line arguments. 
    if (argc != 3) 
    { 
     std::cerr << "Usage: client <host> <port>" << std::endl; 
     return 1; 
    } 

    boost::asio::io_service io_service; 
    s11n_example::client client(io_service, argv[1], argv[2]); 
    io_service.run(); 
    } 
    catch (std::exception& e) 
    { 
    std::cerr << e.what() << std::endl; 
    } 

    return 0; 
} 

structsample .hpp ----

ここで、データはサーバーからクライアントに届いていますが、クライアントからの応答は返されません。

+0

std :: stringはasioバッファとして直接サポートされていませんので、これを読んでください:http://stackoverflow.com/questions/4068249/how-to-use-stdstring-with-asiobuffer –

+0

教えてください、ここで教えてくださいどこに問題があるのですか... handle_read_strまたはasynchonous read .......と変更するもの... char *に変換すべきですか? –

+0

@SvenNilsson std :: stringはasio :: bufferでサポートされていますが、不変バッファ(書き込み用)に対してのみサポートされています。 –

答えて

2

ASIOが実際に転送するものは、のバイトです。文字列は、任意のデータを格納するのに適したコンテナではありません(ヌル文字を含む可能性があり、文字列に含まれていると混乱します)。

はブースト:: ASIO使用して文字列を転送するには、あなたの文字列を取得するために、このバッファ内のデータをのstd ::ベクトルまたはのstd ::配列に基づいてバッファを使用して、分析することをお勧めします。

+0

std :: stringを使用する代わりに、char *を使用して問題を解決しました。ありがとうございますが、クライアントとサーバーからこれらの関数を呼び出した後、サーバーはクライアント側から送信された文字列を非同期に読み取ることができません。 –

+0

は、バッファ内のデータを受信するサーバーですか? –

+0

yess..it is..サーバとクライアントのコードを添付して質問を編集してください。 –

関連する問題