无法获得简单的boost网络示例工作,只是初始化服务器会立即导致错误

时间:2015-10-21 06:36:52

标签: c++ boost boost-asio

我正在运行Xubuntu 14.04和Boost 1.54.0。我已经从this book修改了第4章示例,以便能够在客户端和服务器之间发送任意字符串,但现在程序立即失败。

这是服务器:

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <string>

using namespace boost::asio;

io_service service;
size_t read_complete(
        char* buff, const boost::system::error_code& err, size_t bytes)
{
    if (err) {
        return 0;
    }
    bool found = std::find(buff, buff + bytes, '\n') < buff + bytes;
    return found? 0 : 1;
}

void handle_connections() {
    ip::tcp::acceptor acceptor(
            service, ip::tcp::endpoint(ip::tcp::v4(), 8001));
    std::string buff;
    while (true) {
        ip::tcp::socket sock(service);
        acceptor.accept(sock);
        int bytes = read(sock, buffer(buff.c_str()), bind(read_complete, buff, _1, _2));
        std::string msg(buff, bytes);
        sock.write_some(buffer(msg));
        sock.close();
    }
}

int main(int argc, char* argv[]) {
    handle_connections();
}

直接从书中复制,并经过验证可以正常使用。

这是重现问题所需的最小客户端:

#include <memory>

#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>

using namespace boost::asio;

class Client
{
    public:
        Client(const std::string& server, const std::string& port):
                server(server), port(port)
        {
            service = std::unique_ptr<io_service>(new io_service);
            endpoint = std::unique_ptr<ip::tcp::endpoint>(new ip::tcp::endpoint(
                    ip::address::from_string(server), atoi(port.c_str())));
            boostSocket = std::unique_ptr<ip::tcp::socket>(
                    new ip::tcp::socket(*service));
            std::cout << std::boolalpha << boostSocket.is_open();  // "false"
        }

    private:
        std::string server;
        std::string port;
        std::unique_ptr<io_service> service;
        std::unique_ptr<ip::tcp::socket> boostSocket;
        std::unique_ptr<ip::tcp::endpoint> endpoint;
};

int main()
{
    Client client("127.0.0.1", "8001");
    return 0;
}

运行此程序告诉我套接字永远不会打开。所以我潜入GDB并发现了这一点。为方便起见,我省略了我在每组行之间使用的(gdb) s调试命令。

Client::Client (this=0x7fffffffd7f8, server="127.0.0.1", port="8001")
    at DIRECTORY WHERE I STORED THE CPP FILE:14
14      service = std::unique_ptr<io_service>(new io_service);
    boost::asio::io_service::io_service (this=0x622130) at /usr/include/boost/asio/impl/io_service.ipp:41
41  {
    boost::asio::detail::noncopyable::noncopyable (this=0x622130) at /usr/include/boost/asio/detail/noncopyable.hpp:29
29    noncopyable() {}
    boost::asio::io_service::io_service (this=0x622130) at /usr/include/boost/asio/impl/io_service.ipp:39
39          (std::numeric_limits<std::size_t>::max)())),
    std::numeric_limits<unsigned long>::max () at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/limits:1196
1196          max() _GLIBCXX_USE_NOEXCEPT { return __LONG_MAX__ * 2UL + 1; }
    boost::asio::io_service::io_service (this=0x622130) at /usr/include/boost/asio/impl/io_service.ipp:41
41  {
    boost::asio::detail::service_registry::service_registry<boost::asio::detail::task_io_service, unsigned long> (this=0x622150, o=..., arg=18446744073709551615)
    at /usr/include/boost/asio/detail/impl/service_registry.hpp:29
29  {
    boost::asio::detail::noncopyable::noncopyable (this=0x622150) at /usr/include/boost/asio/detail/noncopyable.hpp:29
29    noncopyable() {}
    boost::asio::detail::posix_mutex::posix_mutex (this=0x622158) at /usr/include/boost/asio/detail/impl/posix_mutex.ipp:33
33  {
    boost::asio::detail::noncopyable::noncopyable (this=0x622158) at /usr/include/boost/asio/detail/noncopyable.hpp:29
29    noncopyable() {}
    boost::asio::detail::posix_mutex::posix_mutex (this=0x622158) at /usr/include/boost/asio/detail/impl/posix_mutex.ipp:34
34    int error = ::pthread_mutex_init(&mutex_, 0);

相关的行是第一行(因为它是我的代码的一部分)和最后一行(它直接进行错误处理)。后续GDB命令仅显示它进一步深入研究Boost的错误处理系统。为什么?我所做的就是创建io_service

1 个答案:

答案 0 :(得分:1)

我必须修复客户端和服务器程序中的错误才能编译。

这是固定服务器:

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <string>

using namespace boost::asio;

io_service service;
size_t read_complete(std::vector<char>const& buff, const boost::system::error_code &err, size_t bytes) {
    if (err) {
        return 0;
    }

    auto last = buff.begin()+bytes;
    bool found = (last != std::find(buff.begin(), last, '\n'));
    return found;
}

void handle_connections() {
    ip::tcp::acceptor acceptor(service, ip::tcp::endpoint(ip::tcp::v4(), 8001));

    std::vector<char> buff(1024);
    while (true) {
        ip::tcp::socket sock(service);
        acceptor.accept(sock);
        int bytes = read(sock, buffer(buff), bind(read_complete, boost::ref(buff), _1, _2));
        sock.send(buffer(buff, bytes));
        sock.close();
    }
}

int main() { handle_connections(); }

有很多变化,最明显的是修复缓冲区的变化。

这是固定客户端。我把所有迷信的使用都归咎于new

#include <memory>

#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>

using namespace boost::asio;

class Client {
  public:
    Client(const std::string &server, const std::string &port) 
        : server(server),
          port(port),
          service(),
          endpoint(ip::address::from_string(server), atoi(port.c_str())),
          boostSocket(service)
    {
        std::cout << std::boolalpha << boostSocket.is_open() << "\n"; // of course, "false"
    }

  private:
    std::string server;
    std::string port;
    io_service service;
    ip::tcp::endpoint endpoint;
    ip::tcp::socket boostSocket;
};

int main() {
    Client client("127.0.0.1", "8001");
    return 0;
}

注意:

  • 您应该使用解析程序来解析地址/端口,而不仅仅是对转换进行硬编码(可能不是IP或端口号)

  • 你从不连接,所以当然套接字没有打开

    boostSocket.connect(endpoint);
    std::cout << std::boolalpha << boostSocket.is_open() << "\n"; // of connected, "true"
    
    /*
     *std::string message("hellow world\n\n\n\n\n");
     *boostSocket.send(buffer(message));
     *streambuf sb;
     *read(boostSocket, sb, boost::asio::transfer_all());
     *std::cout << "RESPONSE: '" << &sb << "'\n";
     */
    

快乐调试