gpt4 book ai didi

c# - 如果我们不从 TcpClient 流中读取,接收到的数据会发生什么

转载 作者:可可西里 更新时间:2023-11-01 02:44:52 26 4
gpt4 key购买 nike

我很好奇 tcp 流中的一个案例。

假设我们创建了一个 TcpClient 并将一些有意义的请求字符串写入传出流。例如一个 Http 请求。

try
{
string requestString = "GET /Api/Test HTTP/1.1 \r\n" +
"Host: 192.168.2.45 \r\n" +
"Connection:close \r\n\r\n";

TcpClient client = new TcpClient();

client.Connect(new IPEndPoint(IPAddress.Parse("192.168.2.45"), 80));

NetworkStream stream = client.GetStream();

byte[] reqBuffer = System.Text.Encoding.Default.GetBytes(requestString);

stream.Write(reqBuffer, 0, reqBuffer.Length);

因此我们的 NIC 会立即从目标套接字收到响应。

这是我的问题:

  1. 传入的字节存储在哪里? (NIC有存储,还是存储在RAM中?)
  2. 如果我们不从应用程序中读取这些字节,我们的 NIC 将如何处理这些字节。

阅读:

if (stream.CanRead)
{
bufferInt = stream.Read(buffer, 0, client.ReceiveBufferSize);
}

最佳答案

与许多其他事物一样,答案在于分层。

那么,让我们从硬件开始:

所有 NIC 都有一些内部缓冲区。这是组装任何响应的第一个位置——但它也是像 TCP 这样的东西并没有多大意义的层次; NIC 只关心它自己的网络协议(protocol),例如以太网或 PPP。在这个层面上,IP 只是一个无差别的有效负载,而 IP 又将 TCP 作为有效负载(尽管应该注意的是,分层远非完美:) 例如,TCP 和 IP 之间存在很多耦合)。

必须先解释传入的数据,然后才能执行任何操作;让我们跳过细节,假设 NIC 缓冲区现在包含一个漂亮的小 TCP/IP 数据包。现在,NIC 驱动程序开始发挥作用——您机器上每个打开的端口都有一个相关联的内存块用于接收数据。基本上,这是您在设置 ReceiveBufferSizeSendBufferSize 时所控制的。驱动程序将指示 NIC 如何处理传入的数据 - 通常,NIC 会使用 DMA 将数据直接发送到 RAM。这非常快——现代 NIC 并不真的需要大型板载内存芯片;即使对于服务器 NIC,该数量通常也在 32 MiB 左右。

这两个 RAM 缓冲区对于您的问题来说是最重要的——当它们已满时,NIC 将简单地丢弃任何进一步到达的数据包。对于具有流量控制的 TCP,它会告诉对方停止传输,谢谢。实际上,这模拟了缓冲流的通常行为——发送方将被阻塞,直到可以再次发送另一条数据为止。发生这种情况时,发送方将重传上次没有成功的数据。对于像 UDP 这样的协议(protocol),没有流量控制,也没有重传,因此您只会不可挽回地丢失数据(甚至没有告诉您有问题)。

如果您有待处理的发送/接收操作(例如 NetworkStream.Read),您还将使用自己的缓冲区 - 这是另一层,但它确实是最不重要的。这里发生的一切是,当操作系统从 NIC 驱动程序获取信息时,它会用内部缓冲区的数据填充您的缓冲区并向您发出信号。在同步场景中(如您的情况),这只会导致您的 Read 调用返回。异步场景在 .NET 和 OS 交互以产生回调中有些棘手,但其余部分几乎相同。例如,这与从本地硬盘驱动器读取文件没有根本区别。

在 .NET 中需要注意的一件重要事情是,您在这些发送/接收中使用的缓冲区在操作期间固定。这意味着缓冲区被禁止在内存中移动,这会降低垃圾收集器的效率(阻止适当的堆压缩);如果您有很多长时间运行的操作,您确实希望尽可能多地重用缓冲区 - 如果您总是为每个操作创建一个新缓冲区,您可能会遇到堆碎片问题。

关于c# - 如果我们不从 TcpClient 流中读取,接收到的数据会发生什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33807443/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com