2013-11-10 14 views
11

Giả sử tôi có một ổ cắm:Làm thế nào để phát hiện khi một ổ cắm tăng tcp ngắt kết nối

std::shared_ptr<tcp::socket> socket(new tcp::socket(acceptor.get_io_service())); 
acceptor.async_accept(*socket, std::bind(handleAccept, this, std::placeholders::_1, socket, std::ref(acceptor))); 

Và tôi lưu trữ một weak_ptr để các ổ cắm cho biết trong một container. Tôi cần điều này vì tôi muốn cho phép khách hàng yêu cầu danh sách các ứng dụng khách khác, vì vậy họ có thể gửi tin nhắn cho nhau.

clients_.insert(socket); // pseudocode 

Sau đó, tôi chạy một số hoạt động async

socket->async_receive(boost::asio::buffer(&(*header), sizeof(Header)) 
    , 0 
    , std::bind(handleReceiveHeader, this, std::placeholders::_1, std::placeholders::_2, header, socket)); 

Làm thế nào để phát hiện khi kết nối được đóng để tôi có thể loại bỏ ổ cắm của tôi từ container?

clients_.erase(socket); // pseudocode 

Trả lời

14

Một ổ cắm ngắt kết nối TCP thường được báo hiệu trong asio bởi một eof hoặc một connection_reset. Ví dụ.

void async_receive(boost::system::error_code const& error, 
        size_t bytes_transferred) 
    { 
    if ((boost::asio::error::eof == error) || 
     (boost::asio::error::connection_reset == error)) 
    { 
     // handle the disconnect. 
    } 
    else 
    { 
     // read the data 
    } 
    } 

Tôi sử dụng boost::signals2 để báo hiệu ngắt kết nối mặc dù bạn luôn có thể chuyển con trỏ đến hàm đến cấp ổ cắm của bạn và sau đó gọi.

Hãy cẩn thận về tuổi thọ ổ cắm và cuộc gọi lại của bạn, xem: boost-async-functions-and-shared-ptrs

+2

Danh sách lỗi có thể tìm thấy tại đây: http: // www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/reference/error__basic_errors.html – aCuria

+0

Tôi nhận thấy rằng điều này thực sự hiệu quả, tôi gặp lỗi "connection_reset". Tuy nhiên, trong tài liệu tôi nhận thấy một mã lỗi khác, "connection_aborted". Có cần phải xử lý mã lỗi này không? – aCuria

+0

Đó là một liên kết hữu ích @aCuria. Một nguồn khác của mã lỗi là tập tin 'boost/system/error_code.hpp'. Đối với lỗi "connection_aborted", tôi đã không nhìn thấy nó trong các ứng dụng của tôi, nhưng không có hại trong thử nghiệm cho nó là tốt. – kenba

1

Có rất nhiều lựa chọn, một số trong số đó là:

  1. Như bạn lưu trữ weak_ptr trong container - nó sẽ không kéo dài tuổi thọ của ổ cắm, nên khi xử lý của bạn sẽ nhận được boost::asio::error::eof (hoặc bất kỳ) , nó sẽ không làm sao chép/di chuyển của shared_ptr, và ổ cắm sẽ bị xóa (nếu bạn không có bất kỳ người nào khác shared_ptr s với nó). Vì vậy, bạn có thể làm điều gì đó như: if(socket.expired()) clients_.erase(socket);

  2. Kiểm tra mã lỗi trong trình xử lý của bạn - nó sẽ cho biết khi nào kết nối bị đóng. Sử dụng thông tin này - bạn có thể gọi clients_.erase từ bộ xử lý.

Could you give an example of #2?

Nó sẽ là một cái gì đó như:

socket->async_receive 
(
    boost::asio::buffer(&(*header), sizeof(Header)), 0, 
    [=, &clients_](const system::error_code& error, size_t bytes_transferred) 
    { 
     if(error) // or some specific code 
     { 
      clients_.erase(socket); // pseudocode 
     } 
     else 
     { 
      // continue, launch new operation, etc 
     } 
    } 
); 
+0

Bạn có thể đưa ra ví dụ về số 2 không? – aCuria

+0

@aCuria Đã thêm ví dụ. –

+0

Tôi không nghĩ rằng tôi nên xóa trên bất kỳ lỗi, một tìm kiếm google nhanh chóng dường như không ném lên một danh sách các mã lỗi đặc biệt cho async_receive mặc dù. – aCuria

Các vấn đề liên quan