非阻塞 UDP 套接字如何 完全没有意义?
我看不出使用它们比阻塞 UDP 套接字有什么优势,也不明白为什么它们作为一种结构存在。书籍没有解决这个问题。我错过了什么?
我了解非阻塞 TCP 套接字在编写可伸缩服务器方面的优势。由于 TCP 套接字(阻塞或非阻塞)表示与 single 远程主机的连接,它只能从该主机发送和接收数据。因此,如果您有 1 个线程服务于 1 个以上的连接,即每个线程有 1 个以上的套接字实例,那么如果其中一个阻塞,则其余线程将不会得到服务。所以你需要一个每个连接 1 个线程的模型(即套接字实例),但这不能很好地扩展,因为每个线程都是有代价的(著名的 C10k 问题)。
非阻塞通过让 1 个线程服务于多个 TCP 连接来解决这个问题。用 Java 的说法,选择器能够判断至少一个通道何时准备好进行 IO,并判断哪些通道准备就绪。非阻塞 IO 中的选择器是跨多个 TCP 套接字的多路复用器。
现在,在 UDP 中,
DatagramSocket
已经充当多路复用器。
单个(阻塞的)UDP 套接字可以从任何远程主机接收(和发送)数据报,所以当我这样做时
import java.net.{DatagramPacket, DatagramSocket}
val udpSocket = new DatagramSocket(<some-port>)
def run(): Unit = {
val packet = new Datagrampacket(new Array[Byte](150), 150)
udpSocket.receive(packet)
// datagram contains the source IP and port.
// do something with the datagram
run()
}
当我从
ANY远程UDP套接字接收数据时,阻塞
receive
将返回。因此,由于 UDP 的性质,只能通过 TCP 中的非阻塞通道/选择器实现的行为可以通过阻塞 UDP 来实现。
这有意义吗?
当我从任何远程 UDP 套接字接收数据时,阻塞接收将返回。
未绑定的 UDP 套接字将从任何远程 UDP 套接字接收数据 - 只要它是针对本地套接字绑定到的特定 IP 和端口。所以,如果你想在你的应用程序中有多个具有不同端口的 UDP 端点,你需要为此创建多个套接字。一个常见的用例是 SIP、H.323、WebRTC 中的实时音频和视频……其中每个媒体通道通常使用不同的端口。
除此之外,实际绑定 UDP 套接字也很有用,这样一个套接字仅从特定的远程端点接收数据。这可以使编程更容易,但也可以通过消除单套接字瓶颈来帮助扩展应用程序。