2010-06-09 1 views
1

См. Код. : P Я могу получать новые соединения до вызова async_accept(). Моя функция делегата также никогда не вызывается, поэтому я не могу управлять любыми соединениями, которые я получаю, что делает новые соединения бесполезными. ;)Приёмник и проблемы с 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; 
} 

EDIT: Я изменил код, чтобы отразить то, что ответы до сих пор говорили. Я перехожу в io_service в ctor моего класса. Как вы можете видеть ниже, main не вызывает запуск службы, поэтому я предполагаю, что ничто не должно быть в состоянии правильно подключиться?

Я положил свой отладчик на строку listen() и перешел на «canyouseeme.org». Набрал 57422 и нажал Connect. Не удалось. Отпустите строку listen(). Был способен подключиться. Это должно быть невозможно? Как никогда? :(

Не знаю, что делать больше. Основной() ниже.

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; 
} 
+0

Почему вы считаете, что соединение должно быть невозможно после прослушивания? Как вы думаете, что слушает? В документации по asio очень четко указано, что basic_socket_acceptor :: listen() помещает акцептор в состояние, в котором он будет слушать новые соединения. –

ответ

3

Так вот мой вопрос. Есть ли способ, чтобы предотвратить Повысьте ASIO акцептор от получения новых соединений на своих собственных и только получение соединений из async_accept()?

вы думаете, почему это происходит? Если вы выложили полный код, который будет в значительной степени помочь. Когда я взять фрагмент и поместить шаблонный главный и io_service :: бежать() вокруг, все работает нормально.

#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 '^]'. 
+0

Полный код добавлен. – bobber205

1

Если вы действительно получаете новое соединение в тот момент, когда вы звоните acceptor->listen() я я озадачен этим. Что вы используете для определения того, получили ли вы соединение или нет? Io_service, как правило, довольно «реагирует» на то, что он реагирует только на события, на которые прямо сказано реагировать.

В приведенном выше примере единственное, что я вижу, что приведет к инициированию «нового соединения», - это вызов async_accept. Кроме того, то, что вы описали, мало соображает с точки зрения низкоуровневых сокетов (с использованием сокетов BSD, как правило, вы должны вызывать bind, listen и accept в этом порядке, и только после этого может быть выполнено новое соединение).

Мое подозрение, что у вас на самом деле есть какая-то ошибочная логика. Кто звонит StartListening и как часто он называется (его нужно только вызывать один раз).Вы потратили дополнительные усилия на настройку своего acceptor объекта, который обычно не нужен в Asio. Обычно вы можете использовать конструктор 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)); 
1

Думаю, вы смешиваете здесь разные вещи.

С одной стороны, вы создаете сокет для обмена данными. Сокет - не что иное, как конечная точка межпроцессного коммуникационного потока через компьютерную сеть. Ваш boost :: asio :: tcp :: socket использует TCP-protocoll для связи; но в общем случае сокет может использовать другие протоколы. Для открытия tcp-socket обычно используется последовательность open-bind-listen-accept на хосте.

С другой стороны, вы анализируете (лежащее в основе) TCP-соединение.

Итак, здесь есть две разные вещи. Хотя для сокета соединение считается «установленным» только после «принятия» хоста, базовое TCP-соединение уже установлено после того, как клиент подключается к прослушивающему сокету. (Одна сторона сервера, это соединение помещается в стек, из которого он отменяется, когда вы вызываете accept()).

Таким образом, единственный способ запретить соединение в вашем случае - не для вызова listen().

 Смежные вопросы

  • Нет связанных вопросов^_^