c# - 如何使用 C#/.Net 使用 TcpClient 发送“n”个数据包
问题描述
我正在尝试使用 TcpClient 发送多个数据包。此代码适用于第一次迭代。但是在第一次迭代之后,服务器没有收到任何东西(尽管循环不断迭代)。服务器端代码运行良好,因为我一直在使用数据包发送方对其进行测试。有什么可以使用 TcpClient 发送数据包突发吗?
TcpClient tcpClient = new TcpClient(localIpAddress,localPort);
tcpClient.NoDelay = true;
tcpClient.Connect(remoteIpAddress,remotePort);
Stream stream=tcpClient.GetStream();
int i = 0;
while (true)
{
i = i + 1;
Console.WriteLine("Message {0} Sent",i);
stream.Write(Encoding.ASCII.GetBytes(message))));
stream.Flush();
Thread.Sleep(500);
}
解决方案
您无法使用 TcpClient 准确控制数据包的发送。事实上,你甚至不能用 TCP Socket() 来做到这一点。您需要使用原始套接字并构建自己的 TCP 数据包。
TCP 堆栈根据套接字配置选项、缓冲区中的信息量、最后一个 ACK 的时间、窗口大小、RTT 以及其他一些信息来决定何时发送数据包。
您可以通过发送大量数据来伪造它,这将迫使 TCP 堆栈以尽可能快的速度立即发送它们。您也可以设置 ,TcpClient.NoDelay()
但这不适用于多次连续写入,除非您在写入之间有合理的延迟,即使这样也不能保证。
您可以进行低级调用来计算发送/接收了多少数据包,但您只能通过调整 TCP 堆栈的参数来影响这一点,即使这样,由于 IP 是有损协议和TCP 数据包将丢失,需要重新传输。
您对上面代码的问题是您正在使用以下行设置 LocalEndPoint:
TcpClient tcpClient = new TcpClient(localIpAddress,localPort);
在套接字通过TIME_WAIT
阶段之前,端口将无法重用,这取决于套接字关闭可能是 120 秒的时间。
将该行更改为:
TcpClient tcpClient = new TcpClient();
或者如果您必须设置源 IP 地址
TcpClient tcpClient = new TcpClient(localIpAddress,0);
您可以在TIME_WAIT
此处阅读以及为什么它是 TCP 协议的固有部分。
作为旁注,stream.Flush();
或者NetworkStream.Flush()
什么都不做。这是它在 .Net 源代码中的实现:
/// <devdoc>
/// <para>
/// Flushes data from the stream. This is meaningless for us, so it does nothing.
/// </para>
/// </devdoc>
public override void Flush() {
}
推荐阅读
- javascript - 从承诺返回的价值总是不确定的
- sql-server - 如何通知用户 Azure blob 触发功能成功/失败?
- android - 将 AVRCP 与两个设备一起使用
- java - 为什么 gif 显示不能与 StdDraw 一起工作而 png 工作?
- c# - 从 asmdef 生成的程序集中使用 monobehaviour
- slack - slack 在用户离开时显示为用户配置的 webhook
- python - 使用`scipy`的$n$维积分的固定阶高斯求积
- html - HTML 响应式电子邮件 - 表格不遵守最大宽度:100%
- python - 我怎样才能转换回来?
- javascript - Vuejs 和引导程序。有条件地禁用按钮组中的按钮