2013-02-25 46 views
6

Tôi có hai chức năng sau để gửi và nhận gói.boost :: asio :: buffer: Lấy kích thước bộ đệm và ngăn chặn tràn bộ đệm?

void send(std::string protocol) 
{ 
    char *request=new char[protocol.size()+1]; 
    request[protocol.size()] = 0; 
    memcpy(request,protocol.c_str(),protocol.size()); 

    request_length = std::strlen(request); 
    boost::asio::write(s, boost::asio::buffer(request, request_length)); 
} 
void receive() 
{ 
    char reply[max_length]; 
    size_t reply_length = boost::asio::read(s, boost::asio::buffer(reply, request_length)); 
    std::cout << "Reply is: "; 
    std::cout.write(reply, reply_length); 
    std::cout << "\n"; 
} 

Các yêu cầu liên quan đến phần này là boost::asio::buffer(reply, request_length) trong đó độ dài yêu cầu là độ dài của chuỗi được thiết lập ban đầu khi gói được gửi. Làm cách nào để kiểm tra kích thước của bộ đệm mà không biết request_length? Một câu hỏi khác là làm thế nào để ngăn chặn tràn bộ đệm?

Trả lời

15

Để có kích thước bộ đệm, chức năng boost::asio::buffer_size() có thể được sử dụng. Tuy nhiên, trong ví dụ của bạn, điều này rất có thể sẽ ít được sử dụng cho bạn.

Như được giải thích trong bộ đệm overview, Boost.Asio sử dụng các lớp đệm để đại diện cho bộ đệm. Các lớp này cung cấp một sự trừu tượng và bảo vệ các hoạt động Boost.Asio chống lại tràn bộ đệm. Mặc dù kết quả của boost::asio::buffer() được chuyển đến các hoạt động, siêu dữ liệu, chẳng hạn như kích thước của bộ đệm hoặc loại cơ bản của nó, không được truyền đi. Ngoài ra, các bộ đệm này không sở hữu bộ nhớ, do đó, nó là trách nhiệm của ứng dụng để đảm bảo bộ nhớ cơ bản vẫn hợp lệ trong suốt thời gian tồn tại của bộ đệm trừu tượng.

Chức năng boost::asio::buffer() cung cấp một cách thuận tiện để tạo các lớp đệm, trong đó kích thước của bộ đệm được suy ra từ loại có thể. Khi Boost.Asio có thể suy ra chiều dài bộ đệm, thì các thao tác Boost.Asio sẽ không gọi tràn bộ đệm khi sử dụng kiểu đệm kết quả. Tuy nhiên, nếu mã ứng dụng chỉ định kích thước của bộ đệm là boost::asio::buffer(), thì đó là trách nhiệm của ứng dụng để đảm bảo rằng kích thước không lớn hơn bộ nhớ cơ bản.

Khi đọc dữ liệu, cần có bộ đệm. Câu hỏi cơ bản trở thành làm thế nào để biết có bao nhiêu bộ nhớ để phân bổ, nếu Boost.Asio không truyền tải kích thước. Có một vài giải pháp cho vấn đề này:

  • Truy vấn ổ cắm có bao nhiêu dữ liệu qua socket::available(), sau đó cấp phát bộ đệm tương ứng.

    std::vector<char> data(socket_.available()); 
    boost::asio::read(socket_, boost::asio::buffer(data)); 
    
  • Sử dụng một lớp Boost.Asio có thể phát triển trong bộ nhớ, chẳng hạn như boost::asio::streambuf. Một số hoạt động, chẳng hạn như boost::asio::read() chấp nhận các đối tượng streambuf làm bộ đệm của chúng và sẽ cấp phát bộ nhớ theo yêu cầu cho hoạt động. Tuy nhiên, điều kiện hoàn thành sẽ được cung cấp; nếu không, hoạt động sẽ tiếp tục cho đến khi bộ đệm đầy.

    boost::asio::streambuf data; 
    boost::asio::read(socket_, data, 
            boost::asio::transfer_at_least(socket_.available())); 
    
  • Ví dụ: Öö Tiib đề xuất, kết hợp chiều dài như một phần của giao thức truyền thông. Kiểm tra Boost.Asio examples để biết ví dụ về các giao thức truyền thông. Tập trung vào giao thức, không nhất thiết phải trên Boost.Asio API.

    • Trong giao thức kích thước cố định, cả nhà sản xuất dữ liệu và người tiêu dùng đều sử dụng cùng một thông báo kích thước. Khi người đọc biết kích thước của thông điệp, người đọc có thể cấp phát bộ đệm trước.
    • Trong giao thức có chiều dài thay đổi, các thư thường được chia thành hai phần: phần đầu và phần thân. Tiêu đề thường có kích thước cố định và có thể chứa nhiều thông tin khác nhau, chẳng hạn như độ dài của phần thân. Điều này cho phép người đọc đọc một tiêu đề vào một bộ đệm kích thước cố định, trích xuất chiều dài cơ thể, cấp phát bộ đệm cho phần thân, sau đó đọc phần thân.

      // Read fixed header. 
      std::vector<char> data(fixed_header_size); 
      boost::asio::read(socket_, boost::asio::buffer(data)); 
      
      protocol::header header(data); 
      network_to_local(header); // Handle endianess. 
      
      // Read body. 
      data.resize(header.body_length()); 
      boost::asio::read(socket_, boost::asio::buffer(data)); 
      
      protocol::body body(data); 
      network_to_local(body); // Handle endianess.  
      
+0

Công cụ tuyệt vời. 'boost :: asio :: streambuff' với' boost :: asio :: read_until() 'làm việc tốt cho tôi trong trường hợp thư kết thúc bằng dấu phân cách. –

1

Tôi nghĩ rằng câu hỏi của bạn là khó hiểu, nhưng điều này có thể giúp:

void receive() { 
    enum { max_length = 1024 }; 
    char reply[max_length]; 
    size_t reply_length; 
    std::cout << "Reply is: "; 
    while ((reply_length = ba::read(s, basio::buffer(reply, max_length))) > 0) { 
    std::cout.write(reply, reply_length); 
    } 
    std::cout << "\n"; 
} 
+0

Lệnh 'boost :: ASIO :: đệm (,)' trả lại những gì chính xác. Tôi thấy rằng nó trả về một cái gì đó trong 'ba :: read (s, buffer (,))' nhưng nó là gì? – pandoragami

+0

@lost_with_coding: Loại đại diện cho bộ nhớ, nhưng không sở hữu bộ nhớ. [Chức năng] (http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/buffer.html) giúp điều chỉnh các loại thường được sử dụng để chúng đáp ứng các yêu cầu loại cho nhiều người trong số các Tăng cường .Asio hoạt động. [Tổng quan] này (http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/overview/core/buffers.html) cung cấp một số thông tin. –

+0

Bạn không cần phải chuyển max_length thành asio :: buffer() trong ví dụ này. (Vì asio có thể lấy nó bằng cách sử dụng 'sizeof'.) –

5

Điển hình là một giao thức truyền thông, hoặc sử dụng các thông điệp dài cố định hoặc tin nhắn có chứa tiêu đề mà nói với chiều dài của tin nhắn.

Boost.Asio online documentation chứa tập hợp lớn các ví dụ và hướng dẫn để bạn có thể bắt đầu từ đó. Wikipedia là nguồn tốt để giải thích thuật ngữ data transmission, tăng tài liệu asio không làm điều đó.

+1

Tôi đã xem qua các hướng dẫn asio tăng nhưng những hướng dẫn này chỉ làm sáng tỏ các ví dụ và không giải thích chi tiết các chức năng gọi, những gì chúng trả về, v.v. Tôi biết tôi có thể nhìn vào các tập tin hpp cũng nhưng đó giống như một cây kim trong đống cỏ khô và thậm chí còn vô dụng hơn so với các ví dụ. Tôi chắc rằng có rất nhiều điều không được nói trong các ví dụ tăng/hướng dẫn nhưng chỉ tìm thấy trong các tập tin hpp mà có thể mất nhiều năm thực hành để tiêu thụ. – pandoragami

+0

@lost_with_coding có lẽ ví dụ asio tăng mong đợi mọi người quen thuộc với khái niệm về truyền thông kỹ thuật số và ý nghĩa của các thuật ngữ liên quan như protcols, khách hàng, máy chủ, yêu cầu, vv được sử dụng trong các ví dụ. Tôi đề nghị chống lại kỹ thuật đảo ngược kiến ​​thức như vậy từ mã, có những nguồn dễ dàng hơn để tìm hiểu tất cả điều đó. –

+0

@lost_with_coding: [ví dụ] (http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/examples.html) không giải thích API nào thực hiện vì được ghi lại trong [tham chiếu ] (http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference.html). Thư viện Boost.Asio phức tạp, không phức tạp. Có một lượng thông tin lớn trong tài liệu, và có thể đáng để dành thời gian để tự làm quen với các phần khác nhau của tài liệu. –

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