У меня есть приложение, которое принимает, обрабатывает и передает UDP-пакеты.
Все работает нормально, если номера портов для приема и передачи различны.
Если номера портов совпадают, а IP-адреса различны, он обычно работает отлично ИСКЛЮЧАЕТ, когда IP-адрес находится в той же подсети, что и компьютер, на котором запущено приложение. В последнем случае для функции send_to требуется несколько секунд, а не несколько миллисекунд, как обычно.
Rx Port Tx IP Tx Port Result
5001 Same 5002 OK Delay ~ 0.001 secs
subnet
5001 Different 5001 OK Delay ~ 0.001 secs
subnet
5001 Same 5001 Fails Delay > 2 secs
subnet
Вот короткая программа, которая демонстрирует проблему.
#include <ctime>
#include <iostream>
#include <string>
#include <boost/array.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::udp;
using std::cout;
using std::endl;
int test( const std::string& output_IP)
{
try
{
unsigned short prev_seq_no;
boost::asio::io_service io_service;
// build the input socket
/* This is connected to a UDP client that is running continuously
sending messages that include an incrementing sequence number
*/
const int input_port = 5001;
udp::socket input_socket(io_service, udp::endpoint(udp::v4(), input_port ));
// build the output socket
const std::string output_Port = "5001";
udp::resolver resolver(io_service);
udp::resolver::query query(udp::v4(), output_IP, output_Port );
udp::endpoint output_endpoint = *resolver.resolve(query);
udp::socket output_socket( io_service );
output_socket.open(udp::v4());
// double output buffer size
boost::asio::socket_base::send_buffer_size option( 8192 * 2 );
output_socket.set_option(option);
cout << "TX to " << output_endpoint.address() << ":" << output_endpoint.port() << endl;
int count = 0;
for (;;)
{
// receive packet
unsigned short recv_buf[ 20000 ];
udp::endpoint remote_endpoint;
boost::system::error_code error;
int bytes_received = input_socket.receive_from(boost::asio::buffer(recv_buf,20000),
remote_endpoint, 0, error);
if (error && error != boost::asio::error::message_size)
throw boost::system::system_error(error);
// start timer
__int64 TimeStart;
QueryPerformanceCounter( (LARGE_INTEGER *)&TimeStart );
// send onwards
boost::system::error_code ignored_error;
output_socket.send_to(
boost::asio::buffer(recv_buf,bytes_received),
output_endpoint, 0, ignored_error);
// stop time and display tx time
__int64 TimeEnd;
QueryPerformanceCounter( (LARGE_INTEGER *)&TimeEnd );
__int64 f;
QueryPerformanceFrequency( (LARGE_INTEGER *)&f );
cout << "Send time secs " << (double) ( TimeEnd - TimeStart ) / (double) f << endl;
// stop after loops
if( count++ > 10 )
break;
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
int main( )
{
test( "193.168.1.200" );
test( "192.168.1.200" );
return 0;
}
Выход из этой программы при работе на компьютере с адресом 192.168.1.101
TX to 193.168.1.200:5001
Send time secs 0.0232749
Send time secs 0.00541566
Send time secs 0.00924535
Send time secs 0.00449014
Send time secs 0.00616714
Send time secs 0.0199299
Send time secs 0.00746081
Send time secs 0.000157972
Send time secs 0.000246775
Send time secs 0.00775578
Send time secs 0.00477618
Send time secs 0.0187321
TX to 192.168.1.200:5001
Send time secs 1.39485
Send time secs 3.00026
Send time secs 3.00104
Send time secs 0.00025927
Send time secs 3.00163
Send time secs 2.99895
Send time secs 6.64908e-005
Send time secs 2.99864
Send time secs 2.98798
Send time secs 3.00001
Send time secs 3.00124
Send time secs 9.86207e-005
Почему это происходит? Есть ли способ уменьшить задержку?
Примечания:
-
Построено с использованием code:: blocks, работающего под различными вариантами Windows
-
Пакет длиной 10000 байтов
-
Проблема исчезает, если я подключу компьютер, запускающий приложение, ко второй сети. Например, WWLAN (сотовая сеть "ракетная палочка" )
Насколько я могу судить, это та ситуация, которую мы имеем:
Это работает (разные порты, одна и та же ЛВС):
Это также работает (одни и те же порты, разные LANS):
Это НЕ работает (те же порты, одна и та же ЛВС):
Кажется, что это работает (те же порты, один и тот же LAN, двухъядерный хост Module2)