2013-01-11 15 views
6

Poniżej znajduje się przykładowy kod dla serwera gniazd przy użyciu wspomagania asio.doładowanie serwera asio zawiesza się w telefonie, aby zamknąć pobudkę :: gniazdo

Ten serwer będzie czekał na porcie 10001, aby dowolny klient mógł się połączyć. Gdy dowolny klient łączy się, uruchomi wątek do odczytania z tego klienta i poczeka na innego klienta. Ale co się dzieje, gdy mój klient rozłącza gniazdo serwera, zawiesza się w rozmowie my_socket->close().

A jeśli nowy klient próbuje połączyć się z serwerem, ulega awarii.

Używam g ++ (4.4.3-4ubuntu5.1 Ubuntu) 4.4.3

#include <ctime> 
#include <iostream> 
#include <string> 
#include <boost/asio.hpp> 
#include <sys/socket.h> 
#include <unistd.h> 
#include <string> 
#include <boost/bind.hpp> 
#include <boost/thread.hpp> 
#include <boost/date_time.hpp> 

using namespace std; 
using boost::asio::ip::tcp; 

void run(boost::shared_ptr<tcp::socket> my_socket) 
{ 
    while (1) 
    { 
     char buf[128]; 
     boost::system::error_code error; 

     size_t len = my_socket->read_some(boost::asio::buffer(buf, 128), error); 
     std::cout << "len : " << len << std::endl; 

     if (error == boost::asio::error::eof) 
     { 
      cout << "\t(boost::asio::error::eof)" << endl; 
      if (my_socket->is_open()) 
      { 
       boost::system::error_code ec; 
       cout << "\tSocket closing" << endl; 
       my_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); 
       cout << "\tShutdown " << ec.message() << endl; 
//    cout << "normal close : " << ::close(my_socket->native_handle()) << endl; 
       my_socket->close(ec); 
       cout << "\tSocket closed" << endl; 
      } 
      break; // Connection closed cleanly by peer. 
     } 
     else if (error) 
     { 
      std::cout << "Exception : " << error.message() << std::endl; 
      break; 
     } 
     else 
     { 
      for (unsigned int i = 0; i < len; i++) 
       printf("%02x ", buf[i] & 0xFF); 
      printf("\n"); 
     } 
    } 
} 

int main() 
{ 
    const int S = 1000; 
    vector<boost::shared_ptr<boost::thread> > arr_thr(S); 

    try 
    { 
     for (uint32_t i = 0;; i++) 
     { 
      boost::asio::io_service io_service; 

      tcp::endpoint endpoint(tcp::v6(), 10001); 

      boost::shared_ptr<tcp::socket> my_socket(new tcp::socket(io_service)); 
      tcp::endpoint end_type; 

      tcp::acceptor acceptor(io_service, endpoint); 

      std::cout << "before accept" << endl; 
      acceptor.accept(*my_socket, end_type); 

      std::cout << "connected... hdl : " << my_socket->native_handle() << std::endl; 

      boost::asio::ip::address addr = end_type.address(); 
      std::string sClientIp = addr.to_string(); 

      std::cout << "\tclient IP : " << sClientIp << std::endl; 
      arr_thr[i] = boost::shared_ptr<boost::thread>(new boost::thread(&run, my_socket)); 
     } 
    } catch (std::exception& e) 
    { 
     std::cerr << e.what() << std::endl; 
    } 

    return 0; 
} 

Odpowiedz

10

Po raz kolejny do pętli w głównych startów zaczniesz nić run, niszcząc i reinicjalizacji lokalna zmienna io_service, następne zdarzenie w gnieździe nadal będzie zakładać stary obiekt io_service prowadzący do awarii.

Powinieneś użyć tylko jednej instancji io_service.

Ponadto, należy spojrzeć na asynchronicznych funkcji boost :: asio który zapewnia, jak async_accept i async_read, patrz na przykład poniższy przykład: http://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio/example/chat/chat_server.cpp

+0

thnx Willem. Pojedyncza instancja io_service rozwiązała mój problem ... –

Powiązane problemy