接受器和Async_Accept的问题

时间:2010-06-09 22:22:25

标签: c++ boost boost-asio

参见代码。 :P 我可以在调用async_accept()之前接收新连接。我的委托函数也从未被调用,所以我无法管理我收到的任何连接,使新连接无用。 ;)

所以这是我的问题。有没有办法阻止Boost ASIO接受器自己获取新连接,只能从async_accept()获取连接?

谢谢!

AlexSocket::AlexSocket(boost::asio::io_service& s): myService(s)
{
    //none at the moment
    connected = false;
    listening = false;

    using boost::asio::ip::tcp;
    mySocket = new tcp::socket(myService);
}

AlexSocket::~AlexSocket()
{
    delete mySocket;
}

bool AlexSocket::StartListening(int port)
{
    bool didStart = false;

    if (!this->listening)
    {
        //try to listen
        acceptor = new tcp::acceptor(this->myService);
        boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
        acceptor->open(endpoint.protocol());
        acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
        acceptor->bind(endpoint);
        //CAN GET NEW CONNECTIONS HERE (before async_accept is called)
        acceptor->listen();

        didStart = true; //probably change?
        tcp::socket* tempNewSocket = new tcp::socket(this->myService);
        //acceptor->async_accept(*tempNewSocket, boost::bind(&AlexSocket::NewConnection, this, tempNewSocket, boost::asio::placeholders::error) );
    }
    else //already started!
        return false;

    this->listening = didStart;
    return didStart;
}

//this function is never called :(
void AlexSocket::NewConnection(tcp::socket* s, const boost::system::error_code& error)
{
    cout << "New Connection Made" << endl;
    //Start new accept async
    tcp::socket* tempNewSocket = new tcp::socket(this->myService);
    acceptor->async_accept(*tempNewSocket, boost::bind(&AlexSocket::NewConnection, this, tempNewSocket, boost::asio::placeholders::error) );
}

bool AlexSocket::ConnectToServer(std::string toConnectTo, string port)
{
    if (connected)
        return false;

    this->serverConnectedTo = toConnectTo;
    this->serverPort = port;

    ip::tcp::resolver resolver(myService);
    ip::tcp::resolver::query newQuery(toConnectTo, port);
    ip::tcp::resolver::iterator myIter = resolver.resolve(newQuery);
    ip::tcp::resolver::iterator end;

    //error
    boost::system::error_code error = boost::asio::error::host_not_found;

    //try each endpoint
    bool connected = false;
    while (error && myIter != end)
    {
        ip::tcp::endpoint endpoint = *myIter++;
        std::cout << endpoint << std::endl;

        mySocket->close();
        mySocket->connect(*myIter, error);

        if (error)
        {
            //try to connect, if it didn't work return false
            cout << "Did not Connect" << endl << error << endl;
        }
        else
        {
            //was able to connect
            cout << "Connected!" << endl;
            connected = true;
        }
        myIter++;
    }   
    this->connected = connected;
    return connected;
}

修改 我已经改变了我的代码以反映到目前为止所说的答案。我正在将io_service传递给我班级的同事。正如你在下面看到的那样,main不是在服务上调用run,所以我认为没有什么能够正确连接?

我已将调试器放在listen()行上并转到“canyouseeme.org”。输入57422并点击Connect。不能。跑听()行。能够连接。这应该不可能吗?从来没有? :(

不知道该怎么办。 main()在下面。

int main()
{
    boost::asio::io_service s;
    AlexSocket test(s);

    test.StartListening(57422);

    test.ConnectToServer("localhost", "57422");

    cout << "Enter something to quit" << endl;
    int a2;
    cin >> a2;

    return 0;
}

3 个答案:

答案 0 :(得分:3)

  

所以这是我的问题。有没有办法阻止Boost ASIO接受器自己获取新连接,只能从async_accept()获取连接?

为什么你认为这种情况发生了?如果您发布了完整的代码,那将非常有帮助。当我拿走你的代码片段并在它周围放置一个样板main和io_service :: run()时,一切正常。

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

#include <iostream>

using namespace boost::asio;

class Socket {
public:
    Socket(
            io_service& io_service
          ) :
        _io_service( io_service ),
        _acceptor( new ip::tcp::acceptor(io_service) )
    {

    }

    bool start(int port)
    {
        //try to listen
        ip::tcp::endpoint endpoint(ip::tcp::v4(), port);
        _acceptor->open(endpoint.protocol());
        _acceptor->set_option(ip::tcp::acceptor::reuse_address(true));
        _acceptor->bind(endpoint);
        //CAN GET NEW CONNECTIONS HERE (before async_accept is called)
        _acceptor->listen();

        ip::tcp::socket* temp = new ip::tcp::socket( _io_service );
        _acceptor->async_accept(
                *temp,
                boost::bind(
                    &Socket::NewConnection,
                    this,
                    temp,
                    boost::asio::placeholders::error
                    )
                );
    }

    void NewConnection(
            ip::tcp::socket* s, 
            const boost::system::error_code& error
            )
    {
        std::cout << "New Connection Made" << std::endl;
        //Start new accept async
        ip::tcp::socket* temp = new ip::tcp::socket( _io_service );
        _acceptor->async_accept(
                *temp,
                boost::bind(
                    &Socket::NewConnection, 
                    this,
                    temp,
                    boost::asio::placeholders::error
                    )
                );
    }
private:
    io_service& _io_service;
    ip::tcp::acceptor* _acceptor;
};

int
main()
{
    io_service foo;
    Socket sock( foo );
    sock.start(1234);
    foo.run();

    return 0;
}

编译并运行

macmini:~ samm$ g++ -lboost_system accept.cc
macmini:~ samm$ ./a.out 
New Connection Made

从其他终端远程登录

macmini:~ samm$ telnet 127.0.0.1 1234
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

答案 1 :(得分:2)

我认为你在这里混合不同的东西。

一方面,您正在创建一个用于数据交换的套接字。套接字只不过是通过计算机网络的进程间通信流的端点。你的boost :: asio :: tcp :: socket使用TCP协议进行通信;但一般来说,套接字可以使用其他协议。对于打开tcp-socket,通常在主机上使用序列open-bind-listen-accept。

另一方面,您分析(底层)TCP连接。

所以这里有两件不同的事情。虽然对于套接字,连接仅在主机的“接受”之后被认为是“已建立”,但是在客户端连接到侦听套接字之后已经建立了基础TCP连接。 (一个是服务器端,该连接放在一个堆栈上,当你调用accept()时它就会从中出列。)

因此,禁止连接的唯一方法是 来调用listen()。

答案 2 :(得分:1)

如果您在致电acceptor->listen()时真正获得新连接,那么我对此感到困惑。你用什么来确定你是否有连接? io_service通常非常“反应”,因为它只对已被明确告知要响应的事件做出反应。

在上面的示例中,我看到的唯一一个会导致启动“新连接”的是调用async_accept。另外,从低级套接字的角度来看,你所描述的内容毫无意义(使用BSD套接字,通常你必须按顺序调用bindlistenaccept,然后才能建立新的联系。)

我怀疑你实际上在某处有一些错误的逻辑。谁调用StartListening以及调用它的频率(它应该只需要调用一次)。你已经经历了一些额外的努力来设置你在Asio中通常不需要的acceptor对象 - 你通常只需使用acceptor构造函数来创建一个包含你需要的所有参数的接受器,并且然后只需致电async_accept

acceptor = new tcp::acceptor(
    this->myService,
    boost::asio::ip::tcp::endpoint(
        boost::asio::ip::tcp::v4(),
        port),
    true);

tcp::socket* tempNewSocket = new tcp::socket(this->myService);
acceptor->async_accept(
    *tempNewSocket, 
    boost::bind(
        &AlexSocket::NewConnection, 
        this, 
        tempNewSocket, 
        boost::asio::placeholders::error) );