我有一個設置,每個200ms(5fps)廣播udp數據包(包含圖像)的多個對等端。雖然同時接受async_receive_from在Linux下的幾個數據包後停止接收
本地流作爲外部流在Windows下正常工作,同樣的代碼(除Windows XP中的socket->cancel();
,見代碼註釋)產生Linux下相當奇怪的行爲:
- 第一按預期收到另一臺機器發送的少量(5〜7)數據包(本機開始流式傳輸時);
- 之後,來自另一臺機器的數據包在不規則的長時間間隔(12s,5s,17s,...)之後被接收,或者超時(在20秒後定義)。在某些時刻,如預期的那樣再次出現(3〜4)個分組的突發。
- 機器本身發送的數據包仍然按照預期收到。
使用Wireshark的,我看到本地外部數據包到達,因爲他們應該,用連續的包裝之間的正確的時間間隔。當本地計算機僅監聽單個其他流並禁用本地流時,行爲也會出現。
這是從接收一些代碼(有一些更新如下建議,謝謝!):
Receiver::Receiver(port p)
{
this->port = p;
this->stop = false;
}
int Receiver::run()
{
io_service io_service;
boost::asio::ip::udp::socket socket(
io_service,
boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(),
this->port));
while(!stop)
{
const int bufflength = 65000;
int timeout = 20000;
char sockdata[bufflength];
boost::asio::ip::udp::endpoint remote_endpoint;
int rcvd;
bool read_success = this->receive_with_timeout(
sockdata, bufflength, &rcvd, &socket, remote_endpoint, timeout);
if(read_success)
{
std::cout << "read succes " << remote_endpoint.address().to_string() << std::endl;
}
else
{
std::cout << "read fail" << std::endl;
}
}
return 0;
}
void handle_receive_from(
bool* toset, boost::system::error_code error, size_t length, int* outsize)
{
if(!error || error == boost::asio::error::message_size)
{
*toset = length>0?true:false;
*outsize = length;
}
else
{
std::cout << error.message() << std::endl;
}
}
// Update: error check
void handle_timeout(bool* toset, boost::system::error_code error)
{
if(!error)
{
*toset = true;
}
else
{
std::cout << error.message() << std::endl;
}
}
bool Receiver::receive_with_timeout(
char* data, int buffl, int* outsize,
boost::asio::ip::udp::socket *socket,
boost::asio::ip::udp::endpoint &sender_endpoint, int msec_tout)
{
bool timer_overflow = false;
bool read_result = false;
deadline_timer timer(socket->get_io_service());
timer.expires_from_now(boost::posix_time::milliseconds(msec_tout));
timer.async_wait(boost::bind(&handle_timeout, &timer_overflow,
boost::asio::placeholders::error));
socket->async_receive_from(
boost::asio::buffer(data, buffl), sender_endpoint,
boost::bind(&handle_receive_from, &read_result,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred, outsize));
socket->get_io_service().reset();
while (socket->get_io_service().run_one())
{
if (read_result)
{
timer.cancel();
}
else if (timer_overflow)
{
//not to be used on Windows XP, Windows Server 2003, or earlier
socket->cancel();
// Update: added run_one()
socket->get_io_service().run_one();
}
}
// Update: added run_one()
socket->get_io_service().run_one();
return read_result;
}
當計時器超過20秒,「已取消操作」將返回錯誤信息,但它很難得到關於正在發生的事情的任何其他信息。
任何人都可以識別問題或給我一些提示,以獲得有關錯誤的更多信息?任何幫助表示讚賞。
如果您希望我們提供幫助,請發表一個[簡短,自包含,正確的示例](http://sscce.org/)以說明問題。特別是,如果沒有'Receiver'類定義或'main()',我們無法編譯您發佈的有限代碼。 – 2012-08-11 19:02:24