2011-09-03 36 views
5

Vì vậy, tôi đã tạo một lớp socket sử dụng boost :: asio library để tạo và đọc không đồng bộ. Nó hoạt động, nhưng tôi có một vài câu hỏi.boost :: asio hoạt động và tài nguyên không đồng bộ

Dưới đây là một ví dụ mã cơ bản:

class Socket 
{ 
public: 
    void doRead() 
    { 
     m_sock->async_receive_from(boost::asio::buffer(m_recvBuffer), m_from, boost::bind(&Socket::handleRecv, this, boost::asio::placeholders::error(), boost::asio::placeholders::bytes_transferred())); 
    } 

    void handleRecv(boost::system::error_code e, int bytes) 
    { 
     if (e.value() || !bytes) 
     { 
      handle_error(); 
      return; 
     } 
     //do something with data read 
     do_something(m_recvBuffer); 

     doRead(); //read another packet 
    } 

protected: 
    boost::array<char, 1024> m_recvBuffer; 
    boost::asio::ip::udp::endpoint m_from; 
}; 

Dường như chương trình sẽ đọc một gói, xử lý nó, sau đó chuẩn bị để đọc khác. Đơn giản. Nhưng nếu tôi thiết lập một nhóm luồng? Cuộc gọi tiếp theo có phải là doRead() trước hoặc sau khi xử lý dữ liệu đã đọc không? Có vẻ như nếu nó được đặt trước do_something(), chương trình có thể ngay lập tức bắt đầu đọc một gói khác, và nếu nó được đặt sau, chủ đề được gắn lên làm bất cứ điều gì do_something(), có thể mất một thời gian. Nếu tôi đặt doRead() trước khi xử lý, điều đó có nghĩa là dữ liệu trong m_readBuffer có thể thay đổi trong khi tôi đang xử lý?

Ngoài ra, nếu tôi đang sử dụng async_send_to(), tôi có nên sao chép dữ liệu được gửi vào bộ đệm tạm thời hay không, vì việc gửi thực sự có thể không xảy ra cho đến sau khi dữ liệu đã nằm ngoài phạm vi? tức là

void send() 
{ 
    char data[] = {1, 2, 3, 4, 5}; 
    m_sock->async_send_to(boost::buffer(&data[0], 5), someEndpoint, someHandler); 
} //"data" gets deallocated, but the write might not have happened yet! 

Ngoài ra, khi đóng socket, tay cầmRecv sẽ được gọi với lỗi cho biết nó bị gián đoạn. Nếu tôi làm

Socket* mySocket = new Socket()... 
... 
mySocket->close(); 
delete mySocket; 

nó có thể gây ra lỗi, bởi vì có một cơ hội mà mySocket sẽ bị xóa trước khi handleRecv() được gọi/kết thúc?

+0

+1 cho một câu hỏi hay, nhưng trong tương lai, tôi khuyên bạn nên tách nó thành các câu hỏi riêng biệt trên Stackoverflow. –

Trả lời

2

Rất nhiều câu hỏi ở đây, tôi sẽ cố gắng giải quyết từng câu hỏi một.

Nhưng nếu tôi thiết lập nhóm chủ đề thì sao?

Cách truyền thống để sử dụng hồ bơi với Boost.Asio là gọi io_service::run()from multiple threads. Tuy nhiên, hãy coi chừng đây không phải là một câu trả lời một kích cỡ phù hợp, có thể có các vấn đề về khả năng mở rộng hoặc hiệu suất, nhưng phương pháp này là dễ nhất để thực hiện. Có nhiều tương tự questions trên Stackoverflow với nhiều thông tin hơn.

Cuộc gọi tiếp theo phải thực hiện trước hoặc sau khi xử lý dữ liệu đọc ? Có vẻ như nếu nó được đặt trước do_something(), chương trình có thể ngay lập tức bắt đầu đọc một gói khác, và nếu nó được đặt sau, chuỗi được gắn lên làm bất cứ điều gì do_something, có thể có thể mất một lúc.

Điều này thực sự phụ thuộc vào những gì do_something() cần làm với m_recvBuffer. Nếu bạn muốn gọi do_something() song song với doRead() bằng cách sử dụng io_service::post(), bạn có thể cần tạo bản sao m_recvBuffer.

Nếu tôi đặt doRead() trước khi xử lý, không có nghĩa là dữ liệu trong m_readBuffer có thể thay đổi trong khi tôi đang xử lý?

như tôi đã đề cập trước đây, có điều này có thể và sẽ xảy ra.

Ngoài ra, nếu tôi đang sử dụng async_send_to(), tôi nên sao chép các dữ liệu được gửi vào một bộ đệm tạm thời, vì gửi thực tế có thể không xảy ra cho đến khi sau khi dữ liệu đã giảm ra khỏi phạm vi?

Là người gọi (bạn) để đảm bảo bộ đệm vẫn nằm trong phạm vi hoạt động không đồng bộ. Như bạn nghi ngờ, ví dụ hiện tại của bạn gọi hành vi không xác định vì data[] sẽ nằm ngoài phạm vi.

Ngoài ra, khi đóng socket, handleRecv() sẽ được gọi là với lỗi cho biết nó bị gián đoạn.

Nếu bạn muốn tiếp tục sử dụng ổ cắm, hãy sử dụng cancel() đến interrupt outstanding hoạt động không đồng bộ. Nếu không, close() sẽ hoạt động. Lỗi được chuyển đến các hoạt động không đồng bộ xuất sắc trong cả hai trường hợp là boost::asio::error::operation_aborted.

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