代码之家  ›  专栏  ›  技术社区  ›  anti

boost::asio向多个客户端发送二进制文件?[重复]

  •  0
  • anti  · 技术社区  · 6 年前

    我可以创建一个简单的TCP服务器来响应一个客户端,但我不知道如何创建一个可以同时处理多个客户端的服务器。我提到过TCP异步服务器之类的例子,但它只是将数据发送到客户端。我需要创建的是,只要客户端存在,就保持连接的活动性。客户端和服务器都将使用Json进行通信。考虑一个客户会给出的情况 {"hello":"Client"} 服务器应该响应 {"Hello":"Server"} ,然后再说一句 {"message":"How are you?"} 以及它的反应 {"response" : "Fine"} .我需要同时处理多个客户。我阅读了聊天服务器文档,但太难理解了。有人能给出如何使用 促进阿西奥 ? 谢谢

    以下是给出的代码:

    #include <ctime>
    #include <iostream>
    #include <string>
    #include <boost/bind.hpp>
    #include <boost/shared_ptr.hpp>
    #include <boost/enable_shared_from_this.hpp>
    #include <boost/asio.hpp>
    #include <json/reader.h>
    #include <json/writer.h>
    
    Json::Value GetRootFromJson(std::string json)
    {
        Json::Value root;
        Json::Reader reader;
        bool success = reader.parse(json, root);
        return root;
    }
    
    std::string GetJsonFromRoot(Json::Value root)
    {
        Json::FastWriter writer;
        std::string json = writer.write(root);
        return json;
    
    }
    
    using boost::asio::ip::tcp;
    
    std::string make_daytime_string()
    {
      using namespace std; // For time_t, time and ctime;
      time_t now = time(0);
      return ctime(&now);
    }
    
    class tcp_connection
      : public boost::enable_shared_from_this<tcp_connection>
    {
    public:
      typedef boost::shared_ptr<tcp_connection> pointer;
    
      static pointer create(boost::asio::io_service& io_service)
      {
        return pointer(new tcp_connection(io_service));
      }
    
      tcp::socket& socket()
      {
        return socket_;
      }
    
      void start()
      {
        //message_ = make_daytime_string();
    
        //Read from client, make json and send appropriate response
        boost::asio::async_read(socket_, boost::asio::buffer(message_),
        boost::bind(&tcp_connection::handle_read, shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
        std::string messageP(message_);
        std::cout << messageP << std::endl;
        Json::Value root = GetRootFromJson(messageP);
        std::string isHello = root["hello"].asString();
        std::string isMessage = root["message"].asString();
        if(!isHello.empty())
        {
            std::string messageTemp = "{\"Hello\":\"Server\"}";
            boost::asio::async_write(socket_, boost::asio::buffer(messageTemp),
            boost::bind(&tcp_connection::handle_write, shared_from_this(),
              boost::asio::placeholders::error,
              boost::asio::placeholders::bytes_transferred));
        }
    
        if(!isMessage.empty())
        {
            std::string messageTemp = "{\"response\":\"Fine\"}";
            boost::asio::async_write(socket_, boost::asio::buffer(messageTemp),
            boost::bind(&tcp_connection::handle_write, shared_from_this(),
              boost::asio::placeholders::error,
              boost::asio::placeholders::bytes_transferred));
        }
    
    
    
        /*
        boost::asio::async_write(socket_, boost::asio::buffer(message_),
            boost::bind(&tcp_connection::handle_write, shared_from_this(),
              boost::asio::placeholders::error,
              boost::asio::placeholders::bytes_transferred));
        */
      }
    
    private:
      tcp_connection(boost::asio::io_service& io_service)
        : socket_(io_service)
      {
      }
    
      void handle_write(const boost::system::error_code& /*error*/,
          size_t /*bytes_transferred*/)
      {
      }
      void handle_read(const boost::system::error_code& /*error*/,
          size_t /*bytes_transferred*/)
      {
          std::cout << "Handle Read of connection\n";
      }
    
      tcp::socket socket_;
      std::string message_;
    };
    
    class tcp_server
    {
    public:
      tcp_server(boost::asio::io_service& io_service)
        : acceptor_(io_service, tcp::endpoint(tcp::v4(), 1936))
      {
        start_accept();
      }
    
    private:
      void start_accept()
      {
        tcp_connection::pointer new_connection =
          tcp_connection::create(acceptor_.get_io_service());
    
        acceptor_.async_accept(new_connection->socket(),
            boost::bind(&tcp_server::handle_accept, this, new_connection,
              boost::asio::placeholders::error));
      }
    
      void handle_accept(tcp_connection::pointer new_connection,
          const boost::system::error_code& error)
      {
        if (!error)
        {
            std::cout << "A client connected" << std::endl;
          new_connection->start();
        }
    
        start_accept();
      }
    
      tcp::acceptor acceptor_;
    };
    
    int main()
    {
      try
      {
        boost::asio::io_service io_service;
        tcp_server server(io_service);
        io_service.run();
      }
      catch (std::exception& e)
      {
        std::cerr << e.what() << std::endl;
      }
    
      return 0;
    }
    

    运行这个程序会让我:

    错误2错误C2679:二进制“=”:未找到接受“const boost::asio::const_buffer”类型右侧操作数的运算符(或没有可接受的转换)C:\boost_1_55_0_dyn\boost\asio\details\u buffers。水电站175

    编辑: 我添加了一个非常简单的客户端代码,可以发送 "{\"Hello\":\"Client\"}" 并期望输出。但是服务器代码,由 塞赫 无法进入 处理你的阅读

    #include <iostream>
    #include <boost/array.hpp>
    #include <boost/asio.hpp>
    
    using boost::asio::ip::tcp;
    
    int main(int argc, char* argv[])
    {
      try
      {
    
        boost::asio::io_service io_service;
    
        tcp::resolver resolver(io_service);
        tcp::resolver::query query("localhost", "1936");
        tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
    
        tcp::socket socket(io_service);
        boost::asio::connect(socket, endpoint_iterator);
    
        std::string message = "{\"hello\":\"Client\"}";
        std::cout << "Sending the message: " << message << std::endl;
        socket.send(boost::asio::buffer(message));
        std::cout << "Sent the message: " << message << std::endl;
        boost::asio::streambuf buf;
        size_t len;
        std::string messageReceived;
        boost::asio::streambuf::mutable_buffers_type mbuf = buf.prepare(512);
        std::cout << "Now receiving message\n";
        std::string messageServer;
        try
        {
            boost::asio::streambuf buf;
            size_t len;
            boost::asio::streambuf::mutable_buffers_type mbuf = buf.prepare(512);
            do {
                len = socket.receive(mbuf);
                std::cout << len << std::endl;
                std::string str(boost::asio::buffers_begin(mbuf), boost::asio::buffers_begin(mbuf) + len);
                messageServer = messageServer + str;
            } while (len>=512); 
        }
        catch (boost::system::system_error err)
        {
            std::cout << err.code() << " " << err.what();
        }
    
        std::cout << messageServer << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << e.what() << std::endl;
      }
    
      return 0;
    }
    

    这是实现服务器的正确方法吗?非常感谢。

    0 回复  |  直到 6 年前
        1
  •  4
  •   sehe    9 年前

    据记载,

    boost::asio::async_read(socket_, boost::asio::buffer(message_),
    

    需要一个streambuf。

    此外,它是一种异步操作,因此 接近感 message_ 在发布读取操作之后,在完成处理程序之前( handle_read )被召回。

    以下内容至少对我有帮助:

    #include <ctime>
    #include <iostream>
    #include <string>
    
    #include <boost/bind.hpp>
    #include <boost/shared_ptr.hpp>
    #include <boost/enable_shared_from_this.hpp>
    #include <boost/asio.hpp>
    
    #include <json/reader.h>
    #include <json/writer.h>
    
    namespace {
        Json::Value to_json(std::string json)
        {
            Json::Value root;
            Json::Reader reader;
            /*bool success =*/ reader.parse(json, root);
            return root;
        }
    
        std::string to_string(Json::Value root) // unused TODO FIXME
        {
            Json::FastWriter writer;
            std::string json = writer.write(root);
            return json;
        }
    }
    
    using boost::asio::ip::tcp;
    
    class tcp_connection : public boost::enable_shared_from_this<tcp_connection>
    {
      public:
        typedef boost::shared_ptr<tcp_connection> pointer;
    
        static pointer create(boost::asio::io_service& io_service)
        {
            return pointer(new tcp_connection(io_service));
        }
    
        tcp::socket& socket()
        {
            return socket_;
        }
    
        void start()
        {
            //Read from client, make json and send appropriate response
            boost::asio::async_read(socket_, message_,
                    boost::bind(&tcp_connection::handle_read, shared_from_this(),
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred));
        }
    
      private:
        tcp_connection(boost::asio::io_service& io_service)
            : socket_(io_service)
        {
        }
    
        void handle_write(const boost::system::error_code& /*error*/,
                size_t /*bytes_transferred*/)
        {
        }
    
        void handle_read(const boost::system::error_code& error, size_t bytes_transferred)
        {
            std::cout << "Handle Read of connection\n";
    
            if (error && error != boost::asio::error::eof) {
                std::cout << "Error: " << error.message() << "\n";
                return;
            }
    
            std::string messageP;
            {
                std::stringstream ss;
                ss << &message_;
                ss.flush();
                messageP = ss.str();
            }
    
            std::cout << messageP << std::endl;
    
            Json::Value root      = to_json(messageP);
            std::string isHello   = root["hello"].asString();
            std::string isMessage = root["message"].asString();
            if(!isHello.empty())
            {
                std::string messageTemp = "{\"Hello\":\"Server\"}";
                boost::asio::async_write(socket_, boost::asio::buffer(messageTemp),
                        boost::bind(&tcp_connection::handle_write, shared_from_this(),
                            boost::asio::placeholders::error,
                            boost::asio::placeholders::bytes_transferred));
            }
    
            if(!isMessage.empty())
            {
                std::string messageTemp = "{\"response\":\"Fine\"}";
                boost::asio::async_write(socket_, boost::asio::buffer(messageTemp),
                        boost::bind(&tcp_connection::handle_write, shared_from_this(),
                            boost::asio::placeholders::error,
                            boost::asio::placeholders::bytes_transferred));
            }
        }
    
        tcp::socket socket_;
        boost::asio::streambuf message_;
    };
    
    class tcp_server
    {
      public:
        tcp_server(boost::asio::io_service& io_service)
            : acceptor_(io_service, tcp::endpoint(tcp::v4(), 1936))
        {
            start_accept();
        }
    
      private:
        void start_accept()
        {
            tcp_connection::pointer new_connection =
                tcp_connection::create(acceptor_.get_io_service());
    
          acceptor_.async_accept(new_connection->socket(),
              boost::bind(&tcp_server::handle_accept, this, new_connection,
                boost::asio::placeholders::error));
        }
    
        void handle_accept(tcp_connection::pointer new_connection, const boost::system::error_code& error)
        {
            if (!error)
            {
                std::cout << "A client connected" << std::endl;
                new_connection->start();
            }
    
            start_accept();
        }
    
        tcp::acceptor acceptor_;
    };
    
    int main()
    {
        try
        {
            boost::asio::io_service io_service;
            tcp_server server(io_service);
            io_service.run();
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }
    }
    
        2
  •  0
  •   kanki66    6 年前

    包括你需要的。有些可能是不必要的:

    boost/asio.hpp , boost/thread.hpp , boost/asio/io_service.hpp

    boost/asio/spawn.hpp , boost/asio/write.hpp , boost/asio/buffer.hpp

    boost/asio/ip/tcp.hpp , iostream , stdlib.h , array , string

    vector , string.h , stdio.h , process.h , iterator

    using namespace boost::asio;
    using namespace boost::asio::ip;
    
    io_service ioservice;
    
    tcp::endpoint sim_endpoint{ tcp::v4(), 4066 };              //{which connectiontype, portnumber}
    tcp::acceptor sim_acceptor{ ioservice, sim_endpoint };
    std::vector<tcp::socket> sim_sockets;
    
    static int iErgebnis;
    int iSocket = 0;
    
    
    void do_write(int a)                                        //gets the postion of the socket in the vector
    {
        int iWSchleife = 1;                                     //to stay connected with putty or something
        static char chData[32000];
        std::string sBuf = "Received!\r\n";
    
        while (iWSchleife > 0)          
        {
            boost::system::error_code error;
            memset(chData, 0, sizeof(chData));
    
            iErgebnis = sim_sockets[a].read_some(boost::asio::buffer(chData), error);           //recv wie bei winsock. simulator empfängt
            iWSchleife = iErgebnis;                                                             //if iErgebnis is bigger then 0 it will stay in the loop. iErgebniss is always >0 when data is received
    
            if (iErgebnis > 0) {
                printf("%d Zeichen empf.vom Client : \n%s\n\n", iErgebnis, chData);
                write(sim_sockets[a], boost::asio::buffer(sBuf), error);
            }
            else {
                boost::system::error_code ec;
                sim_sockets[a].shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);       //close the socket when no data
                if (ec)
                {
                    printf("studown error");                                                    // An error occurred.
                }
            }
        }
    }
    
    void do_accept(yield_context yield)
    {
        while (1)                                                   //endless loop to accept limitless clients
        {
            sim_sockets.emplace_back(ioservice);                    //look to the link below for more info
            sim_acceptor.async_accept(sim_sockets.back(), yield);   //waits here to accept an client
    
            boost::thread dosome(do_write, iSocket);                //when accepts starts the thread do_write and passes the parameter iSocket
            iSocket++;                                              //to know the position of the socket in the vector
    
        }
    }
    
    int main()
    {
        sim_acceptor.listen();
        spawn(ioservice, do_accept);            //here you can learn more about Coroutines https://theboostcpplibraries.com/boost.coroutine
        ioservice.run();                        //from here you jump to do:accept
        getchar(); 
    }