2016-07-04 1 views
1

У меня есть клиент, использующий libwebsocket для установления соединения с сервером. Всякий раз, когда клиент отправляет запрос, сервер отправляет ответ и после получения ответа клиент закрывает соединение. Работает отлично.libwebsocket: как отключить клиент, если нет ответа сервера на некоторое время (с таймаутом)?

Но когда сервер не отвечает на запрос, у меня возникла проблема, что клиент все время ждет ответа. Когда ничего не происходит, обратный вызов никогда не вызывается и его невозможно закрыть соединение с возвратом -1 из функции обратного вызова.

Есть ли способ включить таймаут для закрытия соединения? Или любая возможность закрыть соединение извне функции обратного вызова?

Вот мой код до сих пор:

int callback_function(libwebsocket_context* context, libwebsocket* wsi, enum libwebsocket_callback_reasons reason, void* user, void* in, size_t len) { 

    switch (reason) { 

     case LWS_CALLBACK_CLIENT_ESTABLISHED: { 
      std::cout << "LWS_CALLBACK_CLIENT_ESTABLISHED" << std::endl; 
      libwebsocket_callback_on_writable(context, wsi); 
     } 
     break; 

     case LWS_CALLBACK_CLOSED:{ 
      std::cout << "LWS_CALLBACK_CLOSED" << std::endl; 
     } 
     break; 

     case LWS_CALLBACK_CLIENT_RECEIVE_PONG: 
     case LWS_CALLBACK_CLIENT_RECEIVE:{ 
      std::cout << "LWS_CALLBACK_CLIENT_RECEIVE" << endl; 
      ((char *)in)[len] = '\0'; 
      answers_[current_request] = answers_[current_request] + string((char *)in); 
      if (libwebsocket_is_final_fragment(wsi)){ 
       std::cout << "request:" << requests_[current_request] << std::endl; 
       std::cout << "answer:" << answers_[current_request] << std::endl; 
       current_request++; 
       if(current_request >= answers_.size()) { 
        ready = true; 

        return -1; 
       } 
       libwebsocket_callback_on_writable(context, wsi); 
      } 
     } 
     break; 

     case LWS_CALLBACK_CLIENT_WRITEABLE:{ 
      std::cout << "LWS_CALLBACK_CLIENT_WRITEABLE" << endl; 
      unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 4096 + LWS_SEND_BUFFER_POST_PADDING]; 

      const std::string message = std::string(requests_[current_request]); 

      std::copy(message.begin(), message.end(), &buf[LWS_SEND_BUFFER_PRE_PADDING]); 
      buf[LWS_SEND_BUFFER_PRE_PADDING+(int)message.size()]='\0'; 

      int n = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], (size_t)message.size(), static_cast<libwebsocket_write_protocol>(LWS_WRITE_BINARY)); 

      if (n < 0){ 
       std::cout << kLogErr << "bad things are happening" << std::endl; 
       return -1; 
      } 
      if (n < (int)message.size()) { 
       std::cout << kLogErr << "Partial write LWS_CALLBACK_CLIENT_WRITEABLE" << std::endl; 
       return -1; 
      } 
     } 
     break; 

     default: 
      std::cout << "CALLBACK_DEFAULT: " << reason << endl; 
     break; 
    } 

    return 0; 
} 

vector<string> sendMessage(const string& server, int port, const string& path, const vector<string>& messages, bool& error) { 

    ready = error = false; 
    current_request = 0; 

    requests_ = vector<string>(messages); 
    answers_ = vector<string>(requests_.size(), ""); 
    int ietf_version = -1; /* latest */ 
    wsi_ = libwebsocket_client_connect(context_, server.c_str(), port, 2, path.c_str(), server.c_str(), "origin", NULL, ietf_version); 

    if (wsi_ == NULL) { 
     std::cout << kLogErr << "libwebsocket connect failed server:" << server << " port: " << port << " path: " << path << std::endl; 
     error = true; 
     return vector<string>(); 
    } 

    bool first_time = true; 
    int n = 0; 
    while (n >= 0 && !force_exit && !ready) { 
     n = libwebsocket_service(context_, 0); 
     if(first_time) { 
      libwebsocket_callback_on_writable(context_, wsi_); 
      first_time = false; 
     } 
     if (n < 0){ 
      continue; 
     } 
     if (wsi_ == NULL) { 
      break; 
     } 
    } 
    error = !ready; 
    wsi_ = NULL; 
    return vector<string>(answers_); 
} 

ответ

0

Я решил проблему.

Я запрограммировал таймер в

vector<string> sendMessage(const string& server, int port, const string& path, const vector<string>& messages, bool& error) 

и когда тайм-аут достигает, таймер устанавливает флаг и запускает

libwebsocket_callback_on_writable(context_, wsi_); 

снова. Тогда в

int callback_function(libwebsocket_context* context, libwebsocket* wsi, enum libwebsocket_callback_reasons reason, void* user, void* in, size_t len) 

в случае

LWS_CALLBACK_CLIENT_WRITEABLE 

я проверить флаг и, если он установлен обратный вызов прерывается штрафом

return -1; 

Works!

0

Вы можете попробовать использовать:

case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: 
    return -1; 
break; 

Или

lws_set_timeout 

Но я не 100% уверен, что будет работать , вы также можете попытаться создать вопрос/вопрос на своем GitHub, они склонны отвечать довольно быстро/ясно.

Я также не уверен, что вы должны реализовать

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