Boost logo

Boost Users :

Subject: Re: [Boost-users] boost::asio::asyn_accept handler
From: Christopher Pisz (christopherpisz_at_[hidden])
Date: 2017-03-29 03:28:11


Exact source listing in Visual Studio 2015

//
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2013 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)
//

#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 <functional>

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();

        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*/)
    {
    }

    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(), 13))
    {
        start_accept();
    }

private:
    void start_accept()
    {
        tcp_connection::pointer new_connection =
            tcp_connection::create(acceptor_.get_io_service());

        std::function<void(tcp_connection::pointer new_connection, const
            boost::system::error_code &error)> callback =
            std::bind(&tcp_server::handle_accept, this, new_connection,
                std::placeholders::_1);

        acceptor_.async_accept(new_connection->socket(), callback);
    }

    void handle_accept(tcp_connection::pointer new_connection,
        const boost::system::error_code& error)
    {
        if( !error )
        {
            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;
}

Exact output spew from compilation:
This is against boost 1.55, because that's what I have at home. I use
1.62.0 at work and get the exact same errors.

1> Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:
1> - add -D_WIN32_WINNT=0x0501 to the compiler command line; or
1> - add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.
1> Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\detail\impl\socket_ops.ipp(1953):
warning C4996: 'WSAAddressToStringA': Use WSAAddressToStringW() instead or
define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
1> c:\program files (x86)\windows kits\8.1\include\um\winsock2.h(3556):
note: see declaration of 'WSAAddressToStringA'
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\detail\impl\socket_ops.ipp(2159):
warning C4996: 'WSAStringToAddressA': Use WSAStringToAddressW() instead or
define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
1> c:\program files (x86)\windows kits\8.1\include\um\winsock2.h(3623):
note: see declaration of 'WSAStringToAddressA'
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\detail\impl\socket_ops.ipp(2295):
warning C4996: 'gethostbyaddr': Use getnameinfo() or GetNameInfoW() instead
or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
1> c:\program files (x86)\windows kits\8.1\include\um\winsock2.h(2216):
note: see declaration of 'gethostbyaddr'
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\detail\impl\socket_ops.ipp(2344):
warning C4996: 'gethostbyname': Use getaddrinfo() or GetAddrInfoW() instead
or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
1> c:\program files (x86)\windows kits\8.1\include\um\winsock2.h(2238):
note: see declaration of 'gethostbyname'
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\detail\impl\socket_select_interrupter.ipp(62):
warning C4996: 'inet_addr': Use inet_pton() or InetPton() instead or define
_WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
1> c:\program files (x86)\windows kits\8.1\include\um\winsock2.h(1850):
note: see declaration of 'inet_addr'
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\detail\impl\socket_select_interrupter.ipp(75):
warning C4996: 'inet_addr': Use inet_pton() or InetPton() instead or define
_WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
1> c:\program files (x86)\windows kits\8.1\include\um\winsock2.h(1850):
note: see declaration of 'inet_addr'
1>d:\users\cpisz.christopherpisz\documents\visual studio
2015\projects\consoleapplication1\consoleapplication1\source2.cpp(27):
warning C4996: 'ctime': This function or variable may be unsafe. Consider
using ctime_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
See online help for details.
1> c:\program files (x86)\windows
kits\10\include\10.0.10240.0\ucrt\time.h(475): note: see declaration of
'ctime'
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\basic_socket_acceptor.hpp(1015):
error C2338: AcceptHandler type requirements not met
1> d:\users\cpisz.christopherpisz\documents\visual studio
2015\projects\consoleapplication1\consoleapplication1\source2.cpp(91):
note: see reference to function template instantiation
'boost::asio::async_result<Handler>::type
boost::asio::basic_socket_acceptor<boost::asio::ip::tcp,boost::asio::socket_acceptor_service<Protocol>>::async_accept<Protocol,StreamSocketService,std::function<void
(tcp_connection::pointer,const boost::system::error_code
&)>&>(boost::asio::basic_socket<Protocol,StreamSocketService>
&,AcceptHandler,void *)' being compiled
1> with
1> [
1> Handler=std::function<void (tcp_connection::pointer,const
boost::system::error_code &)>,
1> Protocol=boost::asio::ip::tcp,
1>
 StreamSocketService=boost::asio::stream_socket_service<boost::asio::ip::tcp>,
1> AcceptHandler=std::function<void
(tcp_connection::pointer,const boost::system::error_code &)> &
1> ]
1> d:\users\cpisz.christopherpisz\documents\visual studio
2015\projects\consoleapplication1\consoleapplication1\source2.cpp(91):
note: see reference to function template instantiation
'boost::asio::async_result<Handler>::type
boost::asio::basic_socket_acceptor<boost::asio::ip::tcp,boost::asio::socket_acceptor_service<Protocol>>::async_accept<Protocol,StreamSocketService,std::function<void
(tcp_connection::pointer,const boost::system::error_code
&)>&>(boost::asio::basic_socket<Protocol,StreamSocketService>
&,AcceptHandler,void *)' being compiled
1> with
1> [
1> Handler=std::function<void (tcp_connection::pointer,const
boost::system::error_code &)>,
1> Protocol=boost::asio::ip::tcp,
1>
 StreamSocketService=boost::asio::stream_socket_service<boost::asio::ip::tcp>,
1> AcceptHandler=std::function<void
(tcp_connection::pointer,const boost::system::error_code &)> &
1> ]
1>d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\basic_socket_acceptor.hpp(1015):
error C2064: term does not evaluate to a function taking 1 arguments
1> d:\programing
projects\cplusplus\boost_1_55_0\boost\asio\basic_socket_acceptor.hpp(1015):
note: class does not define an 'operator()' or a user defined conversion
operator to a pointer-to-function or reference-to-function that takes
appropriate number of arguments
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

&amp somehow got put there from copy pasting? It is an actual amperstand in
code.
I am posting via Gmail now. I am not sure if they did it. At work I have to
post through nabble, because they have just about everything blocked.

On Tue, Mar 28, 2017 at 9:23 PM, Gavin Lambert via Boost-users <
boost-users_at_[hidden]> wrote:

> On 29/03/2017 12:02, Christopher Pisz via Boost-users wrote:
>
>> Sigh. I know that code wouldn't work. That is my interpretation of what
>> you
>> gave me. Now you are talking about two arguments and placeholders, but why
>> would I give it a place holder, when I am giving it the argument directly?
>> the tcp_connection::pointer argument is new_connection. The placeholder is
>> for the error code which I am not supplying directly. Either way, it still
>> fails to compile if you add a std::placeholders::_2 on the end.
>>
>
> You need _1 (and only that) in the functor that is passed to async_accept,
> since that expects a callback that takes exactly one error_code argument.
>
> You might need other placeholders if elsewhere you're using functors that
> take more than one argument, as in one previous instance where you were
> using multiple binds or getting a callback passed in externally to then
> rebind locally.
>
> Can we just get a compilable working example of the following method while
>> maintaining the use of the std::function variable? I don't want to bind
>> directly, I don't want to use lambda, I want to have an std::function
>> variable that I can pass to others. It's really a simple 6 line
>> problem....
>>
>
> Just be careful with passing functions outside of the class, as they can
> have hidden dependencies (eg. the below will UB or crash if something tries
> to call the callback after tcp_server has been destroyed).
>
> The following code still fails to compile:
>>
>> void start_accept()
>> {
>> tcp_connection::pointer new_connection =
>> tcp_connection::create(acceptor_.get_io_service());
>>
>> std::function<void(tcp_connection::pointer new_connection, const
>> boost::system::error_code &amp; error)> callback =
>> std::bind(&tcp_server::handle_accept, this, new_connection,
>> std::placeholders::_1);
>>
>> acceptor_.async_accept(new_connection->socket(), callback);
>> }
>>
>
> I still can't see your monitor from where I'm sitting, so I don't know
> what errors it produces. If you want anything more helpful than guesswork,
> then tell people what the errors are; don't just say that it fails. (
> http://www.catb.org/esr/faqs/smart-questions.html)
>
> First off, is that &amp; actually in your source code or is it only being
> added when you email? You need to fix that if it's actually in your code.
>
> Secondly, you shouldn't specify parameter names in the type signature of
> std::function; just use types.
>
> Otherwise, that code looks like it should work, assuming handle_accept has
> a compatible signature.
>
>
>
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net