- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我很好奇 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 会立即从目标套接字收到响应。
这是我的问题:
阅读:
if (stream.CanRead)
{
bufferInt = stream.Read(buffer, 0, client.ReceiveBufferSize);
}
最佳答案
与许多其他事物一样,答案在于分层。
那么,让我们从硬件开始:
所有 NIC 都有一些内部缓冲区。这是组装任何响应的第一个位置——但它也是像 TCP 这样的东西并没有多大意义的层次; NIC 只关心它自己的网络协议(protocol),例如以太网或 PPP。在这个层面上,IP 只是一个无差别的有效负载,而 IP 又将 TCP 作为有效负载(尽管应该注意的是,分层远非完美:) 例如,TCP 和 IP 之间存在很多耦合)。
必须先解释传入的数据,然后才能执行任何操作;让我们跳过细节,假设 NIC 缓冲区现在包含一个漂亮的小 TCP/IP 数据包。现在,NIC 驱动程序开始发挥作用——您机器上每个打开的端口都有一个相关联的内存块用于接收数据。基本上,这是您在设置 ReceiveBufferSize
和 SendBufferSize
时所控制的。驱动程序将指示 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/
下面的代码旨在在首次打开工作簿时运行。 Sub Auto_Open() Dim LastRow As Integer LastRow = Sheet6.UsedRange.Rows.Count Act
当我尝试操作我的代码时,除了弹出调试错误外,它执行得很好。错误信息在这里。 我的完整代码在这里。 #include using namespace std; class String { publi
The invocation of the constructor on type 'WpfApplication1.MainWindow' that matches the specified bi
我正在使用 BaseAdapter: public class MyAdapter extends BaseAdapter{ private final LayoutInflater mInflate
我想做网页抓取。我写了代码 var connection = require('./mysqlConnection'); var c = new Crawler({ maxConnections
我的系统中发生 Java 堆空间错误。我尝试了很多来自 Stack Overflow 的解决方案,但没有任何效果。当我工作时 当按下 OK 然后 (我的项目没有错误) 我的 eclipse.ini 是
环境: i5 750 DDR3 4GWin7 专业版 x64 sp1 DXSDK 9.0c 2010 年 6 月 GeForce GT240(驱动程序 275.33)512MB MSVC 2008 s
这段代码是我写的。 import socket host = 'localhost' port = 3794 s = socket.socket(socket.AF_INET, socket.SOCK
我正在尝试引用 UTC 时间间隔获取本地日期时间,我正在执行下面的代码。 var dtString =DateTime.UtcNow.ToString(@"yyyy-MM-ddTHH\:mm\:ss
我有一个非常简单的 C# 问题,它从库中加载 Windows WPF 窗口。这是代码: public partial class App : Application { public App(
我目前正在使用带有导航组件的底部导航,它工作正常但是当我们点击导航项 fragment 正在加载然后闪烁正在发生,即使当前选择的项目也会发生闪烁。它在加载 fragment 时发生。我的应用程序屏幕背
我是新来的 kotlin , 当我开始 Null Safety 时,我对下面的情况感到困惑. There's some data inconsistency with regard to initia
我有一个框,其中包含同时发生的两个独立的 css 转换。 当转换发生时,图标下方的标题和段落文本移动位置 参见 JS Fiddle:http://jsfiddle.net/Lsnbpt8r/ 这是我的
在为黑莓 10 构建电话间隙应用程序时,我遇到了异常情况。 [BUILD] Populating application source [BUILD] Parsing config.xml [
这个问题在这里已经有了答案: How to properly stop the Thread in Java? (8 个回答) 3年前关闭。 我看过How to properly stop the T
我试图弄清楚发生 fatal error 时如何刷新页面。基本上我正在访问图像 api 并将图像复制到我的服务器。我还每次都创建照片的缩略图版本。我会每隔一段时间收到一条错误消息,指出我的脚本试图分配
我正在尝试使用断言函数检查元素是否在屏幕上。我在我的测试应用程序 (AndroidDriver) 中使用 Appium 和 Java。我期望的是,如果元素在屏幕上,则返回 1;如果不在屏幕上,则返回
我正在开发图像上传系统。我使用 CommonsMultipartResolver 设置 maxUploadSize。当我尝试上传超过最大尺寸的图像文件时,会发生 MaxUploadSizeExcced
我有以下代码和@ComponentScan(basePackages = "com.project.shopping"),包结构为 com.project.shopping.Controller co
我尝试运行此程序作为测试,但收到错误“发生了 JNI 错误,请检查您的安装并重试”,然后是“发生了 Java 异常”。关于如何解决这个问题有什么想法吗? package java; public cl
我是一名优秀的程序员,十分优秀!