他们的角色是什么(一般来说)?
当你想要通过套接字发送数据时,数据会被复制到套接字的发送缓冲区,因此你的代码不必等待数据真正从网络中发送出去才能继续执行。当发送调用成功返回时,这仅意味着数据已被放置到发送缓冲区中,协议实现将在准备好发送该数据时从中读取它。
请记住,多个进程的多个套接字可能同时想要发送数据,但在任何时候只能发送一个数据包。当发送正在进行时,所有其他发送者都必须等待,一旦线路空闲,实现每次只能处理一个发送请求。
从网络上到达的数据由协议实现写入套接字的接收缓冲区中,在那里等待你的代码从那里读取它。否则,所有的接收都必须停止,直到你的代码处理了传入的数据包,然而,你的代码可能在后台处理一个数据包到达的同时做其他事情,而且接口是共享的,所以系统必须避免其他进程无法接收其网络数据,因为你的进程拒绝处理自己的传入数据。
它们是每个套接字独有的缓冲区吗?
是的。每个套接字都有自己的一组缓冲区。
Transport层的缓冲区(例如TCP缓冲区)和这些缓冲区之间是否有连接?
如果您指的是TCP接收和发送窗口,那么答案是肯定的。
TCP会定期告诉另一端接收缓冲区还剩多少空间,这样另一端就不会发送超过接收缓冲区容量的数据。如果接收缓冲区已满,则另一端将完全停止发送,直到有空间为止,只要您读取了部分数据。
因此,如果您无法频繁地读取数据以防止套接字缓冲区被填满,则增加接收缓冲区大小可以避免TCP连接暂停发送数据。
另一方面,如果发送缓冲区已满,套接字将不会接受来自代码的更多数据。任何尝试发送的操作都会在没有空间时被阻塞或失败(非阻塞套接字),直到有空间为止。
TCP 只能使用当前在发送缓冲区中的数据进行工作,因此发送缓冲区的大小也会影响 TCP 的发送行为。TCP 发送策略可能取决于各种因素,其中之一是已知要发送的数据量。例如,如果您的发送缓冲区只有 2 KB,那么 TCP 将永远不会看到超过 2 KB 的发送数据,尽管您的应用程序可能知道还有更多数据要跟随。如果您的发送缓冲区为 256 KB,并且您将 128 KB 的数据放入其中,则 TCP 将知道必须为该连接发送 128 KB 的数据,这可能会(并且极有可能)影响 TCP 使用的发送策略。
当使用流式套接字(TCP)和使用无连接套接字(UDP)时,它们是否有不同的行为/角色?
是的。因为对于 TCP,您发送的数据只是一串字节流。字节与被发送的数据包之间没有关系。发送 80 字节可能意味着发送一个具有 80 字节的数据包,也可能意味着发送 10 个每个 8 字节的数据包。TCP 将自行决定。传入的数据也同理。如果您的接收缓冲区中有 200 字节,您无法知道这些字节是如何到达的,从 TCP 套接字中读取的字节数可能使用任意数量的数据包进行传输。因此,尽管通过基于数据包的网络以块传输数据,TCP 连接的行为就像是串行线路链接。
另一方面,UDP发送数据报。如果您将80字节放入UDP套接字的发送缓冲区中,则这80字节一定会以单个包发送出去,其中包含80字节的有效负载数据。数据发送的方式与将其写入发送缓冲区的方式完全相同。如果您一个接一个地写入80个字节,则会发送80个包,每个包都包含一个字节。 如果您告诉TCP套接字要发送200字节但发送缓冲区中只有100字节的空间,那么TCP将向缓冲区添加100字节,并让您知道添加了100个字节中的100个字节。 另一方面,UDP会阻塞或失败并显示错误,因为所有的200字节要么全部适合要么全部不适合; UDP没有部分适合。
此外,当接收时,数据报存储在UDP接收缓冲区中,而不是字节。如果TCP套接字首先接收到80字节数据,然后再接收到200字节数据,您可以执行读取调用来一次性读取所有280字节。如果UDP套接字首先接收到带有80字节的数据报,然后是带有200字节的数据报,并且您请求从中读取280字节,则您只能得到80字节,因为由读取调用返回的所有数据必须来自同一数据报。 您无法跨越数据报边界读取。 还要注意,如果您仅请求读取20个字节,则会接收到数据报的前20个字节,另外60个字节将被丢弃。下一次读取数据时,它将来自大小为200字节的下一个数据报。
因此,两个句子的区别在于:TCP套接字将字节存储在套接字缓冲区中,而UDP套接字将数据报存储在套接字缓冲区中。并且数据报必须完全适合缓冲区,无法完全适合套接字缓冲区的传入数据报会被静默丢弃,即使缓冲区还有一些空间可用。