[英]How to buffer data for send() and select()?
盡管send()在大多數時間都發送完所有數據后都成功了,但情況並非總是如此。 因此,建議人們對select()和poll()使用write-fdset來檢查套接字何時可寫。
通常的機制在保持可理解的源代碼的同時,看起來如何實際上緩沖要發送的數據?
我對套接字編程的* nix方面並不十分熟悉,但是在Win32方面遇到了相同的問題。 緩沖並不是什么大問題(您將請求排入隊列,並在寫入完成后進行窺視以從隊列中提交下一個),真正的問題是需要緩沖實際上正在處理流控制且無法解決流控制的信號僅使用緩沖:總是有一個消費者比生產者慢,並且緩沖基本上將失去控制。 您必須將流控制向上傳播到生成數據的任何模塊,這使接口變得非常復雜。 所有“寫”請求必須支持指示流控制狀態的返回碼(即“停止寫,沒有更多空間!”)和回調,以邀請調用者恢復寫操作。
因為我們在C ++領域,所以可以將數據存儲在std :: vector中
新數據將附加到向量的末尾。 當您收到套接字可寫的通知時,請嘗試發送完整的向量。 send()將返回實際發送了多少。 然后只需從向量的開頭擦除該字節數即可:
std::vector<char> buffer;
...
if( ! buffer.empty() )
{
int bytesRead = send( socket, &buffer[ 0 ], buffer.size(), flags );
if( bytesRead > 0 )
buffer.erase( 0, bytesRead );
else
// some error...
}
因此,可能還有更多錯誤檢查要做,但是您明白了嗎?
而不是對每個單獨的發送請求進行排隊,這樣做的好處是,假設您正在使用TCP,則可以將多個更高級別的發送合並到一個套接字發送中。
但是正如Remus正確提到的那樣,您的流控制和API有點棘手-即如何阻止緩沖區過大?
在編寫需要以select()/ poll()循環為中心的OO時,您需要一個良好的抽象。 我一直發現自適應通信環境(ACE)Reactor類對此非常有用。 道格·施密特(Doug Schmidt)撰寫了兩本書《 C ++網絡編程》,涵蓋了這種環境,並且網絡上還有其他各種內容,包括《 ACE Reactor的設計和使用》。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.