他们的角色(通常)是什么?
您想通过套接字发送的数据被复制到套接字的发送缓冲区,因此您的代码不必等待(=block)直到数据真正发送到网络。当 send 调用成功返回时,这仅意味着数据已被放入发送缓冲区中,一旦准备好通过网络发送该数据,协议实现就会从该缓冲区读取它。
请记住,来自多个进程的多个套接字可能都希望同时发送数据,但任何时候都只能通过网络线路发送一个数据包。在发送过程中,所有其他发送者必须等待,一旦线路空闲,实现只能处理一个又一个发送请求。
来自网络的数据由协议实现写入套接字的接收缓冲区,在那里它将等待您的代码从那里读取它。否则,所有接收都必须停止,直到您的代码处理完传入的数据包,但是您的代码可能会在数据包到达后台时执行其他操作,并且接口是共享的,因此系统必须避免其他进程无法接收其网络数据只是因为您的进程拒绝处理自己的传入数据。
它们是每个套接字的缓冲区吗?
是的。每个套接字都有自己的一组缓冲区。
传输层的缓冲区(例如 TCP 缓冲区)和这些缓冲区之间是否存在连接?
我不确定您所说的“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 个字节有效负载数据的单个 UDP 数据包中发送出去。数据的发送方式与您将其写入发送缓冲区的方式完全相同。如果你一个接一个地写80个字节,就会发出80个包,每个包一个字节。如果您告诉 TCP 套接字发送 200 个字节,但发送缓冲区中只剩下 100 个字节空间,TCP 将向缓冲区添加 100 个字节,并让您知道 200 个字节中的 100 个已添加。另一方面,UDP 将阻塞或失败并出现错误,因为所有 200 个字节都适合或不适合; UDP 不适合。
同样在接收时,数据报存储在 UDP 接收缓冲区中,而不是字节。如果 TCP 套接字首先接收 80 字节数据,然后接收 200 字节数据,您可以执行一次读取所有 280 字节的读取调用。如果 UDP 套接字首先接收到一个 80 字节的数据报,然后是一个 200 字节的数据报,并且您请求从中读取 280 个字节,那么您得到的正好是 80 个字节,因为读取调用返回的所有数据都必须来自同一个数据报。您不能跨数据报边界读取。另请注意,如果您请求仅读取 20 个字节,则会收到数据报的前 20 个字节,而其他 60 个字节将被丢弃。下次读取数据时,将从下一个大小为 200 字节的数据报中读取。
所以两句话的区别:TCP 套接字将字节存储在套接字缓冲区中,UDP 套接字将数据报存储在套接字缓冲区中。并且数据报必须完全适合缓冲区,不能完全适合套接字缓冲区的传入数据报会被静默丢弃,即使缓冲区有一些可用空间。