首页 > 解决方案 > 如何使用 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);
                
            } 

标签: c#.netsocketsservertcpclient

解决方案


您无法使用 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() {
    }

推荐阅读