2010-07-04 3 views
0

Я пытаюсь реализовать протокол irc очень просто. Моя первая попытка - использовать boost :: asio и подключиться к серверу и прочитать motd. AFAIK motd отправляется каждому клиенту при их подключении. Я выполнил следующую тестовую программу и, похоже, ничего не сделал. Это не очень хороший код, но это все, что у меня есть после нескольких разочаровывающих часов.Почему boost :: asio ничего не делает

#define _WIN32_WINNT 0x0501 
#include <iostream> 
#include <boost/asio.hpp> 
#include <boost/bind.hpp> 
#include <boost/function.hpp> 
#include <queue> 



class IrcConnection 
{ 
public: 
    IrcConnection(const std::string& server, int port, boost::function<void (const std::string&)> onMessage, boost::asio::io_service& io_service): s(server), p(port), onM(onMessage), ios(io_service), socket(io_service) 
    { 
    } 
    void connect() 
    { 
     somethingHappened = false; 
     //DNS stuff 
     boost::asio::ip::tcp::resolver resolver(ios); 
     boost::asio::ip::tcp::resolver::query query(s , "0"); 
     boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query); 
     boost::asio::ip::tcp::resolver::iterator end; 

     boost::system::error_code error; 

     while(iter != end) 
     { 
      boost::asio::ip::tcp::endpoint endpoint = iter->endpoint(); 
      endpoint.port(p); 
      socket.close(); 
      socket.connect(endpoint, error); 
      iter++; 
     } 
     if(error) 
     { 
      std::cout << "ERROR" << std::endl; 
      std::cout << error << std::endl; 
     } 

     std::cout << "Connected to: " << socket.remote_endpoint().address().to_string() << std::endl; 

     //read from the socket until a space is found 
     boost::asio::async_read_until(socket, currentData, ' ', boost::bind(&IrcConnection::onReceiveFinished, this, boost::asio::placeholders::error)); 
    } 
    void disconnect() 
    { 
     socket.close(); 
    } 
    void send(int priority, const std::string& message) 
    { 
    } 
bool somethingHappened; 

private: 
    std::string s; 
    int p; 
    boost::function<void (const std::string&)> onM; 
    boost::asio::io_service& ios; 
    boost::asio::ip::tcp::socket socket; 
    std::priority_queue<std::string> outQueue; 
    boost::asio::streambuf currentData; 


    void onReceiveFinished(const boost::system::error_code& error) 
    { 
     if(error) 
     { 
      disconnect(); 
      std::cout << "ERRORRRR" << std::endl; 
      std::cout << error << std::endl; 
     } 

     std::cout << "STUFF IS OCCURING" << std::endl; 
     somethingHappened = true; 

     std::istream stream(&currentData); 
     std::string data; 
     std::getline(stream, data); 

     boost::asio::async_read_until(socket, currentData, ' ', boost::bind(&IrcConnection::onReceiveFinished, this, boost::asio::placeholders::error)); 
     ios.dispatch(boost::bind(onM, data)); 
    } 


}; 


void onMe(const std::string& x) 
{ 
    std::cout << "MESSAGE" << std::endl; 
    std::cout << x << std::endl; 
} 

int main() 
{ 
    boost::asio::io_service ios; 
    std::string server = "irc.efnet.org"; 
    int port = 6667; 

    IrcConnection x(server, port, onMe, ios); 

    x.connect(); 

    while(!x.somethingHappened) 
    { 
     // 
    } 

    return 0; 

} 

Программа пытается подключиться к irc.efnet.org и читать, пока пространство не будет отправлено, а затем выплевывает, что данные на терминал. Однако я запускаю это, и все, что напечатано, является ip-адресом того, к чему я подключился, и затем программа не заканчивается.

Что мне нужно сделать, чтобы получить свое отступы?

+0

Асинхронные каркасы IO, C++ и намоточные устройства, все в одном вопросе ... какой кошмар: D –

+2

@Matt: ASIO при правильном использовании - это очень фантастическая библиотека, ничто в C++ или даже на других языках не приближается к что он может предложить. Научитесь использовать его перед жалобами. :) – Hippicoder

+0

@ Hippicoder: Я признаю, что я никогда не использовал его. У меня было много возможностей сделать это, но я не соглашусь говорить на других языках (я думаю, вы имеете в виду рамки здесь) не имеют превосходных решений. –

ответ

2

Если вы выполняете асинхронные вызовы, вы должны отправлять запросы в io_service. В вашем случае после "x.connect();" позвоните по номеру "ios.run();"

Просто помните, если вы не сделаете никаких дальнейших сообщений после возврата асинхронного обратного вызова, запустите exit/return.

btw в "ios.dispatch(boost::bind(onM, data));" is onM предназначено для onMe?

+0

connect не является асинхронным, async_connect - это. –

+0

OnM - это метод, локальный для объекта. Я передаю указатель функции в инициализации. Это также устранило мою проблему, спасибо большое! –

+0

@ Hippocoder: Есть ли у вас какие-либо предложения или ресурсы, на которые я могу смотреть, пока я развиваюсь с boost :: asio? Я предпочитаю не беспокоиться об этом каждый раз, когда сталкиваюсь с небольшой проблемой. –

-1

Вы смешиваете асинхронные (io_service::post, async_read_until) и синхронные (, ip::tcp::endpoint::resolve) операции. Это может работать, но я действительно не предлагаю такой подход. Придерживайтесь асинхронных операций, используйте ip::tcp::socket::async_connect вместо ip::tcp::socket::connect и ip::tcp::socket::async_resolve вместо ip::tcp::socket::resolve. Вам нужно будет вызвать io_service::run или его эквивалент, поэтому ваш код ничего не делает после connect. Документация Boost.Asio содержит numerous examples, где показано, как достичь этого.

+0

Почему этот ответ был отменен? –

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