[英]Variable-size buffer for receiving UDP packets
我有一個UDP套接字,它將接收一些可能不同大小的數據包,我會異步處理它:
socket.async_receive_from(boost::asio::buffer(buffer, 65536), senderEndpoint, handler);
這里的問題是,為了處理不同的大小,我有一個很大的緩沖區,可以通過可變大小的緩沖區來解決。
據我所知,當使用async_receive_from
,一次只調用一個數據包,因為數據包邊界在UDP中保留。 那么, 有沒有辦法給async_receive_from
一個空緩沖區,以便Asio增長到適合數據包大小 ?
另請注意,我包裝了數據包,因此對於每個傳輸到此套接字的數據包,4個第一個字節是數據包的長度。
有關更精確的答案,請參閱詳細說明的代碼。
首先,我們需要在不填充緩沖區的情況下調用接收處理程序。 這是使用boost::asio::null_buffer()
(有關更多信息,請參閱reactor-style操作 ,如Tanner所述)。
void UDPConnection::receive()
{
socket.async_receive(boost::asio::null_buffers(), receive_handler);
}
現在,當接收到數據包時,將receive_handler
而不填充任何緩沖區。
現在,對於處理程序:
void UDPConnection::handleReceive(const boost::system::error_code& error, unsigned int)
{
// Standard check: avoid processing anything if operation was canceled
// Usually happens when closing the socket
if(error == boost::asio::error::operation_aborted)
return;
使用socket.available()
,我們可以獲得要讀取的字節數。 重要提示:此數字不一定是數據包的大小! 對於我的測試,這個數字總是大於數據包大小(即使是8 kB數據包,這是我的計算機可以處理的最大數據包)。
// Prepare buffer
unsigned int available = socket.available();
unsigned char* buffer = new unsigned char[available];
魔術發生在這里:“真正的”接收呼叫在這里完成,並且通常會很快,因為它只會填充一個緩沖區。 此調用只會使一個數據包出列(即使在調用時,套接字中有多個數據包)。 返回值在這里很重要,因為只有緩沖區的一部分可能已被填充。 例如: 可用= 50,packetSize = 13 。
// Fill it
boost::asio::ip::udp::endpoint senderEndpoint;
boost::system::error_code ec;
unsigned int packetSize = socket.receive_from(boost::asio::buffer(buffer, available), senderEndpoint, 0, ec);
現在,只是標准的錯誤檢查/處理/等...
if(ec)
{
// ...
}
// Process packet
// ...
receive();
}
你可以手工完成。 my_socket.available()
返回在要讀取的套接字中排隊等待的下一個Udp數據包的大小。 因此,您可以使用它來檢查下一個數據包的大小,相應地增大緩沖區然后接收它。 但是,我同意這些評論者的意見,那就是效率低於僅使用最大可能的大小作為緩沖區。 除非最大值比平均數據包大很多,否則您的應用程序通常根本不需要接收它。
但這是一個優化問題。 您的問題的答案是available()
並自己增加緩沖區。
編輯:我知道這在異步情況下不太理想,因為如果在調用available()
時已經等待,則available()
僅返回下一個udp數據包的大小。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.