Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Acceptor和Async_Accept的问题_C++_Boost_Boost Asio - Fatal编程技术网

C++ Acceptor和Async_Accept的问题

C++ Acceptor和Async_Accept的问题,c++,boost,boost-asio,C++,Boost,Boost Asio,见代码:P 我能够在调用async_accept()之前接收新连接。我的委托函数也从未被调用,因此我无法管理接收到的任何连接,从而使新连接无效。;) 这是我的问题。有没有办法防止Boost ASIO acceptor自己获取新连接,而只从async_accept()获取连接 谢谢 AlexSocket::AlexSocket(boost::asio::io_service& s): myService(s) { //none at the moment connected

见代码:P 我能够在调用async_accept()之前接收新连接。我的委托函数也从未被调用,因此我无法管理接收到的任何连接,从而使新连接无效。;)

这是我的问题。有没有办法防止Boost ASIO acceptor自己获取新连接,而只从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;
}
AlexSocket::AlexSocket(boost::asio::io_服务&s):myService(s)
{
//目前没有
连接=错误;
倾听=错误;
使用boost::asio::ip::tcp;
mySocket=newtcp::socket(myService);
}
AlexSocket::~AlexSocket()
{
删除mySocket;
}
bool-AlexSocket::StartListening(int端口)
{
bool didStart=false;
如果(!此->正在侦听)
{
//试着去听
acceptor=新tcp::acceptor(此->myService);
boost::asio::ip::tcp::endpoint端点(boost::asio::ip::tcp::v4(),端口);
acceptor->open(endpoint.protocol());
acceptor->set_选项(boost::asio::ip::tcp::acceptor::reuse_address(true));
接受者->绑定(端点);
//可以在此处获取新连接(在调用async_accept之前)
接受者->倾听();
didStart=true;//可能会改变吗?
tcp::socket*tempNewSocket=newtcp::socket(this->myService);
//acceptor->async_accept(*tempNewSocket,boost::bind(&AlexSocket::NewConnection,this,tempNewSocket,boost::asio::placeholders::error));
}
否则//已经开始了!
返回false;
这->倾听=开始;
返回didStart;
}
//永远不会调用此函数:(
void-AlexSocket::NewConnection(tcp::socket*s,const-boost::system::error\u代码和错误)
{
cout async_accept(*tempNewSocket,boost::bind(&AlexSocket::NewConnection,this,tempNewSocket,boost::asio::placeholders::error));
}
bool-AlexSocket::ConnectToServer(std::string-to-connectto,string-port)
{
如果(已连接)
返回false;
此->服务器连接到=连接到;
此->服务器端口=端口;
ip::tcp::解析器解析器(myService);
ip::tcp::resolver::QueryNewQuery(ToConnectionTo,端口);
ip::tcp::resolver::迭代器myIter=resolver.resolve(newQuery);
ip::tcp::解析器::迭代器端;
//错误
boost::system::error\u code error=boost::asio::error::host\u未找到;
//尝试每个端点
布尔连接=假;
while(error&&myIter!=end)
{
ip::tcp::endpoint=*myIter++;
标准::无法连接(*myIter,错误);
如果(错误)
{
//尝试连接,如果不起作用,返回false
库特
我的问题是,有没有办法防止Boost ASIO acceptor单独获取新连接,而只从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;
}
来自另一个终端的telnet

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

如果您在调用
acceptor->listen()
时真正获得了一个新的连接,那么我对此感到困惑。您使用什么来确定是否获得了连接?io_服务通常是非常“被动”的,因为它只对显式要求它作出反应的事件作出反应

在上面的示例中,我看到的唯一一件会导致启动“新连接”的事情是调用
async\u accept
。此外,从低级套接字的角度来看,您所描述的没有什么意义(使用BSD套接字,通常必须按顺序调用
bind
listen
accept
,然后才能建立新连接)

我的怀疑是,您实际上在某个地方有一些错误的逻辑。谁调用了
StartListening
,调用频率是多少(应该只需要调用一次)。为了设置Asio中通常不需要的
acceptor
对象,您已经付出了大量额外的努力-您通常可以使用
acceptor
构造函数创建一个包含所有所需参数的接受器,然后只需调用
async\u 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) );

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

一方面,您正在创建用于数据交换的套接字。套接字只不过是计算机网络上进程间通信流的端点。boost::asio::tcp::socket使用tcp协议进行通信;但通常,套接字可以使用其他协议。打开tcp套接字时,通常使用在主机上依次打开绑定侦听接受

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

因此这里有两种不同的情况。对于套接字,连接只有在主机的“接受”之后才被视为“建立”,而在客户端连接到侦听套接字之后,底层TCP连接已经建立。(一种是服务器端,该连接被放在堆栈上,当调用accept()时,它将从堆栈中退出))


因此,在您的情况下,禁止连接的唯一方法是不要调用listen()。

为什么您认为在listen之后连接不可能?您认为listen做了什么?asio文档非常清楚地指出,basic_socket_acceptor::listen()将接受程序置于侦听新连接的状态。
macmini:~ samm$ telnet 127.0.0.1 1234
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
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) );