- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我有一个接收、处理和传输 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(蜂窝网络“火箭棒”)
据我所知,这是我们的情况:
这有效(不同的端口,相同的 LAN):
这也有效(相同的端口,不同的 LANS):
这不起作用(相同的端口,相同的 LAN):
这似乎可行(相同的端口、相同的 LAN、双宿主 Module2 主机)
最佳答案
鉴于在 Windows 上观察到大型数据报的目标地址与发送方在同一子网内不存在的对等方,问题可能是 send()
阻塞等待的结果对于 Address Resolution Protocol (ARP) 响应以便可以填充第 2 层以太网帧:
发送数据时,第 2 层以太网帧将填充路由中下一跃点的媒体访问控制 (MAC) 地址。如果发送方不知道下一跳的 MAC 地址,它将广播 ARP 请求并缓存响应。使用发件人的子网掩码和目标地址,发件人可以确定下一跳是否与发件人在同一子网上,或者数据是否必须通过默认网关路由。根据问题中的结果,发送大型数据报时:
套接字的send buffer size (SO_SNDBUF
) 被设置为 16384
字节,但发送的数据报的大小为 10000
。缓冲区饱和时send()
的行为没有具体说明,但有些系统会观察到send()
阻塞。在这种情况下,如果任何数据报产生延迟(例如等待 ARP 响应),饱和将很快发生。
// Datagrams being sent are 10000 bytes, but the socket buffer is 16384.
boost::asio::socket_base::send_buffer_size option(8192 * 2);
output_socket.set_option(option);
考虑让内核管理套接字缓冲区大小或根据您的预期吞吐量增加它。
当发送的数据报大小超过 Window 的注册表 FastSendDatagramThreshold
参数时,send()
调用会阻塞,直到数据报发送完毕。有关详细信息,请参阅 Microsoft TCP/IP Implementation Details :
Datagrams smaller than the value of this parameter go through the fast I/O path or are buffered on send. Larger ones are held until the datagram is actually sent. The default value was found by testing to be the best overall value for performance. Fast I/O means copying data and bypassing the I/O subsystem, instead of mapping memory and going through the I/O subsystem. This is advantageous for small amounts of data. Changing this value is not generally recommended.
如果观察到每个 send()
到发送方子网上的 existing peer 的延迟,则配置和分析网络:
另请注意,在等待 ARP 解析时快速连续发送低于 FastSendDatagramThreshold
值的数据报可能会导致数据报被丢弃:
ARP queues only one outbound IP datagram for a specified destination address while that IP address is being resolved to a media access control address. If a User Datagram Protocol (UDP)-based application sends multiple IP datagrams to a single destination address without any pauses between them, some of the datagrams may be dropped if there is no ARP cache entry already present. An application can compensate for this by calling the
iphlpapi.dll
routineSendArp()
to establish an ARP cache entry, before sending the stream of packets.
关于c++ - 发送 UDP 数据包的长时间延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33875210/
使用 Python 的 rtmplib 绑定(bind)并遇到一些问题。 首先, 我有这样的东西: import librtmp conn = librtmp.RTMP(...) conn.con
基本上,我是在查看 Motorstorm 排行榜时在 PS3 上窃听数据包。排行榜以 XML 格式发送到我的 ps3,但只有在我获得授权后。那么有人可以告诉我这三个数据包之间发生了什么,以及我如何在浏
我正在努力了解 TCP,但解析大量 RFC 并没有帮助。我相信我了解连接和关闭握手,但我似乎无法找到任何总结实际数据流的内容。 在连接和关闭握手之间 TCP 数据包看起来像什么? (特别是标题) 最佳
我正在尝试通过 RCON 端口与我的 Minecraft 服务器通信。 虽然我不知道如何使用套接字和流的东西。四处寻找,我发现他们都有一些共同点。套接字、输入流和输出流。 我在我的代码中试过了,但返回
我正在 UDP 之上设计一个简单的协议(protocol),现在我意识到其他人可以将数据包发送到我正在监听的端口。这样的数据包对于我的应用程序来说显然是不正确的(我现在不担心安全问题) 是否有过滤这些
我目前有一个具有可自定义滴答率的游戏服务器,但在本示例中,我们建议服务器每秒仅滴答一次或 1hz。我想知道如果客户端发送速率比服务器快,因为我当前的设置似乎不起作用,那么处理传入数据包的最佳方法是什么
我无法理解网络字节顺序以及通过 UDP 发送和接收数据的顺序。我正在使用 C#。 我有一个结构保持: message.start_id = 0x7777CCCC; message.me
我正在为 USB 设备编写代码。假设 USB 主机开始控制读取传输以从设备读取一些数据,并且请求的数据量(设置数据包中的 wLength)是端点 0 最大数据包大小的倍数。那么在主机接收到所有数据后(
我有一台 Windows PC、Marvell 交换机、Netgear 交换机和一台 Ubuntu 机器连接在一起(通过 Netgear 交换机)。 我最近从 Windows PC 向 Marvell
在查看数据包字节码时,您将如何识别 dns 数据包。 IP header 的协议(protocol)字段会告诉后面有一个 UDP 帧,但是在 UDP 帧内没有协议(protocol)字段来指定接下来会
我有一个通过 udf 的 802.11 (wifi) 上各种类型的流量的 pcap。由于 MTU,udp(或更准确地说是 IP)对 wifi 数据包进行分段。我目前正在使用 SharpPcap 读取并
我正在开发的 Core Audio 应用程序上有此崩溃日志。我目前正在调试它,所以我的问题不是关于崩溃本身,而是关于 的含义“k”包 . 这是什么意思 ? 我已阅读 this , 和 this (关于
我在一台 VM Ubuntu 16.04 机器上的 100 个多播组上生成 UDP 数据包,并在另一台 VM Ubuntu 16.04 机器上订阅这些组。两者都在由 Hyper-V 管理器运行的 HP
这个问题在这里已经有了答案: How can I fix 'android.os.NetworkOnMainThreadException'? (66 个回答) 6年前关闭。 我正在尝试创建一个简单的
我正在寻找使用 Java 来欺骗 UDP 数据包。是否有任何好的 Java 库可以让您创建自己的 RAW SOCKETS? 最佳答案 我会使用包装 libpcap 的 Java API . libpc
我在基于 Tyrus 的客户端和 tomcat Web 服务器之间使用没有压缩的 websocket。我在 tomcat 端看到消息传入和传出我的套接字,但如果我设置一个wireshark来观察它们传
我的应用程序在模拟器中运行时无法接收 UDP 数据包。 UDP 数据包由“localhost”上的以下 java 程序通过端口 49999 发送。 DatagramSocket clien
我正在开发一个 Google Glass 应用程序,它需要在工作线程中监听 UDP 数据包(与发送 UDP 数据包的现有系统集成)。我之前发布了一个问题(请参阅 here )并收到了一个答案,其中提供
我正在从客户端向服务器发送两个数据包。我遇到的问题是,在服务器上读取的数据使两个字符串对于发送的最长字符串具有相同的长度。例如: 如果字符串 1 为:1234 字符串 2 为:abcdefghi 服务
我知道这是不好的做法,但是可以执行以下操作吗? Send packet1 to UDP port 1 port 1 receives packet1 and sends it to port 2 po
我是一名优秀的程序员,十分优秀!