2015-04-25 2 views
1

Я обычно не типа, чтобы размещать вопрос, и больше искать, почему что-то не работает сначала, но на этот раз я сделал все, что мог, и я просто не могу выяснить, что не так.libircclient: Отборочное соединение абсолютно невозможно отладить

Так вот вещь:

Я сейчас программирование IRC Bot, и я использую libircclient, небольшая библиотека C для обработки соединений IRC. Он работает очень хорошо, он выполняет свою работу и прост в использовании, но ...

Я подключаюсь к двум различным серверам, поэтому я использую настраиваемый сетевой цикл, который использует функцию select. На моем персональном компьютере в этом цикле нет проблем, и все отлично работает.

Но (вот в чем проблема), на моем удаленном сервере, где будет размещен бот, я могу подключиться к одному серверу, но не к другому.

Я попытался отладить все, что мог. Я даже пошел изучать источники libircclient, посмотреть, как это работает, и поместить некоторые printfs, где я мог, и я мог видеть, откуда он исходит, но я не понимаю, почему он это делает.

Так вот код для сервера (Объекты irc_session_t инкапсулированы, но это нормально вроде легко понять, не стесняйтесь задавать для получения дополнительной информации, если вы хотите.):

// Connect the first session 
first.connect(); 

// Connect the osu! session 
second.connect(); 

// Initialize sockets sets 
fd_set sockets, out_sockets; 

// Initialize sockets count 
int sockets_count; 

// Initialize timeout struct 
struct timeval timeout; 

// Set running as true 
running = true; 

// While the server is running (Which means always) 
while (running) 
{ 
    // First session has disconnected 
    if (!first.connected()) 
     // Reconnect it 
     first.connect(); 

    // Second session has disconnected 
    if (!second.connected()) 
     // Reconnect it 
     second.connect(); 

    // Reset timeout values 
    timeout.tv_sec = 1; 
    timeout.tv_usec = 0; 

    // Reset sockets count 
    sockets_count = 0; 

    // Reset sockets and out sockets 
    FD_ZERO(&sockets); 
    FD_ZERO(&out_sockets); 

    // Add sessions descriptors 
    irc_add_select_descriptors(first.session(), &sockets, &out_sockets, &sockets_count); 
    irc_add_select_descriptors(second.session(), &sockets, &out_sockets, &sockets_count); 

    // Select something. If it went wrong 
    int available = select(sockets_count + 1, &sockets, &out_sockets, NULL, &timeout); 

    // Error 
    if (available < 0) 
     // Error 
     Utils::throw_error("Server", "run", "Something went wrong when selecting a socket"); 

    // We have a socket 
    if (available > 0) 
    { 
     // If there was something wrong when processing the first session 
     if (irc_process_select_descriptors(first.session(), &sockets, &out_sockets)) 
      // Error 
      Utils::throw_error("Server", "run", Utils::string_format("Error with the first session: %s", first.get_error())); 

     // If there was something wrong when processing the second session 
     if (irc_process_select_descriptors(second.session(), &sockets, &out_sockets)) 
      // Error 
      Utils::throw_error("Server", "run", Utils::string_format("Error with the second session: %s", second.get_error())); 
    } 

Проблема в этом коде является то, что строки:

irc_process_select_descriptors(second.session(), &sockets, &out_sockets) 

Всегда возвращает ошибку в первый раз, это называется и только для одного сервера. Странно, что на моем компьютере с Windows он работает отлично, а на сервере Ubuntu он просто не хочет, и я просто не могу понять, почему.

Я сделал некоторые углубленные отладки, и я увидел, что libircclient делает это:

if (session->state == LIBIRC_STATE_CONNECTING && FD_ISSET(session->sock, out_set)) 

И это, где все идет не так. Состояние сеанса правильно установлено в LIBIRC_STATE_CONNECTING, но, во-вторых, FD_ISSET (session-> sock, out_set) всегда возвращает false. Он возвращает true для первого сеанса, но для второго сеанса никогда.

Два сервера: irc.twitch.tv:6667 и irc.ppy.sh:6667. Серверы правильно настроены, и пароли сервера тоже верны, так как все работает отлично на моем персональном компьютере.

Извините за очень длинный пост.

Заранее благодарен!

ответ

0

Хорошо, после нескольких часов отладки у меня наконец возникла проблема.

Итак, когда сеанс подключен, то он войдет в состояние LIBIRC_STATE_CONNECTING, а затем при вызове irc_process_select_descriptors, он будет проверить это:

if (session->state == LIBIRC_STATE_CONNECTING && FD_ISSET(session->sock, out_set)) 

Проблема заключается в том, что выбор() будет изменять наборы розетки, и удалит все наборы, которые не актуальны.

Итак, если сервер не отправил никаких сообщений перед вызовом irc_process_select_descriptors, FD_ISSET вернет 0, потому что select() считает, что этот сокет не имеет значения.

Я установил его, просто писать

if (session->state == LIBIRC_STATE_CONNECTING) 
{ 
    if(!FD_ISSET(session->sock, out_set)) 
     return 0; 

    ... 
} 

Так это будет сделать программу ждать, пока сервер не послал нам что-нибудь.

Извините, что вы не проверили все!