Boost asio async_accept works under Windows but fails under FreeBSD. What's wrong?

时间:2017-06-15 10:32:27

标签: c++ windows boost-asio freebsd

EDIT: Looks like it's not my code but the build environment. That's both good and bad because now I know that the code is OK but have no idea how to debug the environment. Any suggestions here? Bear in mind that I do not have admin privileges on this computer.

I'm stuck trying to make simple code work under FreeBSD. It's a call to async_accept from Boost 1.64 asio that does not behave. Same code works fine under Windows but under FreeBSD it accepts the client connection (the connect call on the client end succeeds) but never calls its handler. Not even sure how to approach this. (Note that unlike other related questions I DO call io_service.run()) Please help.

Self contained code that shows the problem:

#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>

namespace asio = boost::asio;
namespace ph = asio::placeholders;
namespace sys = boost::system;
using asio::ip::tcp;

static void accept_handler(const sys::error_code& error)
{
    // THIS IS NEVER CALLED UNDER FREEBSD
    if (error)
        std::cout << "failed to connected to server" << std::endl;
    else
        std::cout << "connected to server" << std::endl;
}

int main(int argc, char* argv[])
{
    if (argc < 3)
    {
        std::cerr << "Usage: accept_test <port> <1 for async and 0 for sync accept>" << std::endl;
        return 1;
    }

    asio::io_service io_service;
    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), atoi(argv[1])));

    std::cout << "waiting for server connection ";
    tcp::socket sock(io_service);

    if (argv[2][0] == '1')
    {

        //THIS WORKS UNDER WIN BUT DOESN'T CALL HANDLER UNDER FREEBSD
        std::cout << "using async accept..." << std::endl;
        acceptor.async_accept(sock, boost::bind(&accept_handler, ph::error));
    }
    else
    {
        //THIS WORKS FINE UNDER BOTH WIN AND FREEBSD
        std::cout << "using sync accept..." << std::endl;
        sys::error_code error;
        acceptor.accept(sock, error);
        if (error)
            std::cout << "failed to connected to server" << std::endl;
        else
            std::cout << "connected to server" << std::endl;
    }

    io_service.run();
    return 0;
}

2 个答案:

答案 0 :(得分:2)

我怀疑您的构建环境存在问题。同步和异步都在工作:

  • FreeBSD 12.0-CURRENT(GENERIC)#0 r319859:Mon Jun 12 19:37:22 UTC 2017
  • FreeBSD clang version 4.0.0(标签/ RELEASE_400 / final 297347)(基于LLVM 4.0.0)

    Target: x86_64-unknown-freebsd12.0
    Thread model: posix
    InstalledDir: /usr/bin
    
  • Boost 1.64.0(来自端口)

使用

构建
# clang++ -std=c++11 -o test -isystem /usr/local/include/ ./test.cpp -L /usr/local/lib -lboost_system

产生的二进制文件:

# ldd test
test:
        libboost_system.so.1.64.0 => /usr/local/lib/libboost_system.so.1.64.0 (0x80083c000)
        libc++.so.1 => /usr/lib/libc++.so.1 (0x800a3f000)
        libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800d06000)
        libm.so.5 => /lib/libm.so.5 (0x800f24000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x801151000)
        libc.so.7 => /lib/libc.so.7 (0x801367000)
        libthr.so.3 => /lib/libthr.so.3 (0x80172e000)

enter image description here

构建env的粗略指令:

vagrant init freebsd/FreeBSD-12.0-CURRENT
vagrant up --provider virtualbox
vagrant ssh
su
pkg install lang/clang-devel
pkg install devel/boost-all
# copy test.cpp

答案 1 :(得分:2)

我的猜测是你正在运行Boost 1.57或更早版本。 kqueue反应器在某些版本中被破坏,正是您所看到的症状。您应该升级到更高版本。对我来说,它在FreeBSD上的1.59工作正常。