Tôi đang cố gắng kết bạn với những người bạn asio và SSL. Mọi thứ diễn ra tốt đẹp, nhưng có một điều gây ra sự bất tiện: cách phát hiện xem kết nối ngang hàng và phân biệt nó với tình huống khi bạn chỉ mất một chút thời gian để gửi dữ liệu, để tiếp tục sau vài giây?boost :: asio và async SSL stream: làm thế nào để phát hiện kết thúc dữ liệu/kết nối gần?
- tăng 1,48
- OpenSSL 1.0.0e
- Biên soạn mã 32-bit sử dụng VS10
- Làm việc trên W7 x64.
Sự nhầm lẫn của tôi xuất phát từ thực tế, hành vi asio khác với ổ cắm thông thường và luồng SSL. Nếu tôi sử dụng tcp :: socket - tôi gặp lỗi EOF khi kết nối ngang hàng. Nhưng để tăng :: asio :: ssl :: stream - nó là không phải như vậy. Thay vào đó, async_read_some trả về 0 dưới dạng byte được chuyển, và nếu tôi cố gắng tiếp tục đọc từ luồng SSL - trả về short_error (http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/overview/core/streams.html).
Vì vậy, các câu hỏi là: hành vi được mong đợi hay tôi định cấu hình sai?
Khách hàng đoạn mã:.
class client
{
public:
// bla-bla-bla-bla-bla ....
//
void handle_write(const boost::system::error_code& error)
{
if (!error)
{
socket_.async_read_some(boost::asio::buffer(reply_, max_length),
boost::bind(&client::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
std::cout << "Write failed: " << error.message() << "\n";
}
}
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
std::cout << "Bytes transfered: " << bytes_transferred << "\n";
if (!error)
{
std::cout << "Reply: ";
std::cout.write(reply_, bytes_transferred);
std::cout << "\n";
std::cout << "Reading...\n";
socket_.async_read_some(boost::asio::buffer(reply_, max_length),
boost::bind(&client::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else if (0 != bytes_transferred)
{
std::cout << "Read failed: " << error.message() << ":"
<< error.value() << "\n";
}
}
private:
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
boost::asio::streambuf request_;
char reply_[max_length];
};
Nếu chúng ta loại bỏ if (! = 0 bytes_transferred), chúng tôi sẽ nhận được "ngắn đọc" :(
Nếu chúng ta sẽ sử dụng mã như-ai , sản lượng sẽ là một cái gì đó như thế này:
Yêu cầu là:
GET/HTTP/1.0
Cookie: Nama-nama = Vala-vala
Bytes chuyển: 1024
Trả lời: HTTP/1.0 200 ok Content-type: text/html
..... bla -bla-bla ....
Reading ... Bytes chuyển: 1024
..... bla bla-bla-.... ..... bla bla-bla- ....
Reading ... Bytes chuyển: 482
..... bla bla-bla-....
Reading ...
Bytes chuyển: 0
Đồng thời, nếu thay vì async_read_some chúng ta viết mã, để làm gì ổ cắm thông thường sẽ trở lại EOF:
boost::asio::async_read(socket_, response_,
boost::asio::transfer_at_least(1),
boost::bind(&client::handle_read_content, this,
boost::asio::placeholders::error));
sau đó cho SSL socket chúng tôi sẽ nhận được 0 như byte chuyển giao, và sau đó short_read.
Tôi biết rằng không có cách nào để phát hiện ngắt kết nối trong trường hợp nếu ngang hàng, ví dụ , đã được rút phích cắm khỏi mạng. Nhưng làm thế nào để phát hiện xung đột rõ ràng trong sạch khi xảy ra tình huống khi ngang hàng không gửi dữ liệu trong một thời gian, nhưng có thể sẽ làm điều đó một chút sau?
Hoặc, có thể tôi không làm gì đó không ổn?
WBR, Andrey
Một số addentum: SSL/TLS có ký hiệu để thông báo cho bên kia về đóng kết nối. Nó đóng cảnh báo. Cũng có thể đóng socket TCP bên dưới. Vì vậy, về cơ bản, câu hỏi của tôi là: tại sao, trong điều kiện tương tự (TCP socket đã được đóng cửa rõ ràng) tôi nhận được EOF trong trường hợp tcp :: socket, và không nhận được bất cứ điều gì để tăng :: asio :: ssl: :suối.
Tính năng lỗi hoặc asio?
Một addentum khác: Vì một số lý do, asio không cung cấp cho tôi EOF nếu SSL nhận được close_notify cũng như TCP socket cơ bản đã bị đóng.
Có, tôi có thể phát hiện các kết nối đã chết vào thời gian chờ. Nhưng làm thế nào tôi có thể phát hiện các kết nối SSL được đóng đúng cách? Bằng cách nhận short_read?
SSL/TLS có ký hiệu để thông báo cho bên kia về việc đóng kết nối. Nó đóng cảnh báo. Ngoài ra TCP socket đang được đóng. Vì vậy, về cơ bản, câu hỏi của tôi là: tại sao, trong điều kiện tương tự (TCP socket đã được đóng lại rõ ràng) Tôi nhận được EOF trong trường hợp tcp :: socket, và không nhận được bất cứ điều gì cho boost :: asio :: ssl :: stream . Lỗi hoặc tính năng? – Amdei
Chắc chắn, 'close_notify' là dành cho đóng cửa sạch sẽ, điều đó sẽ không giúp bạn phát hiện ra những cái xấu. Tôi không biết nhiều về 'boost :: asio :: ssl :: stream', nhưng tôi đoán là bạn đang thực hiện các hoạt động không đồng bộ và việc đóng SSL/TLS sẽ gây ra vấn đề với các hoạt động không đồng bộ (xem" Đóng kết nối SSLSocket "đúng cách) ở trên). Nó có thể giải thích một hành vi hơi khác. Dù bằng cách nào, nó không thực sự quan trọng. Nó sẽ không phải là một lỗi mà cần sửa chữa, vì nó chỉ không phải là cách chính xác để tìm ra khi nào ngừng đọc từ một dòng/ổ cắm. – Bruno
Nhân tiện, tôi không chắc chắn ý của bạn là gì "* Nó đóng cảnh báo. Ngoài ra ổ cắm TCP bên dưới bị đóng. *", Nhưng cảnh báo đóng cửa TLS không ngụ ý rằng ổ cắm TCP bên dưới phải được đóng lại. – Bruno