socket编程的阻塞模式效率低下,但却是Java中典型socket编程的精髓。但是,还有其他技术。例如采用异步套接字通道,通过套接字建立通信,这可以大大降低效率。
插座
在典型的套接字编程情况下,即使用 TCP 和 UDP 套接字的情况下,I/O 操作以阻塞和同步模式工作。这意味着当客户端套接字的线程调用读取操作时,它会阻塞服务器,直到数据可用。如果底层缓冲区已满,这也可能会阻止写入。这使得其他客户端套接字线程停止,直到通道被释放。这种类型的通道阻塞显然是低效的。为了克服这种情况。相反,可以做的是等到线程完成其工作。客户端套接字可以在服务器提供数据后立即通知;同时,其他线程可以做其他事情,直到来自服务器的数据到达。如果服务器有多个打开的套接字,另一种方法是创建单独的线程进行通信。无论哪种情况,这都是一种解决方法,而不是适当的解决方案。然而,正如我们将看到的,Java 通过 SocketChannel 为这个问题提供了一个解决方案。
套接字通道
另一方面,套接字通道是与服务器套接字建立通信的非阻塞方式。在这里,我们可以让一个线程同时与多个打开的连接进行通信。这是通过向 Selector 添加一堆 SocketChannel 来实现的。选择器对象位于客户端和服务器之间。客户端套接字线程通过循环选择器的 select 方法来获取套接字通道。它可以通知套接字通道的状态是否已被接受、接收数据或关闭。这种技术可以在单个线程中与多个客户端进行通信,而无需维护多个线程和同步的开销。你可以在图 1 中看到这一点。
异步套接字通道
支持异步套接字通道的类实际上是 Java NIO API 库的一部分。思路是通过sockets实现非阻塞异步IO通信。异步 IO 利用回调代码在 IO 完成时执行,非阻塞的思想是指立即返回的 IO 操作,可以有数据,也可以没有数据,或者错误代码。这意味着,在从非阻塞通道读取时,返回值或阻塞通道没有延迟,直到返回有形的东西。有两个与异步套接字操作相关的关键类。它们是 AsynchronousServerSocketChannel 和 AsynchronousSocketChannel;两者都可以在名为 java.nio.channels 的包中找到。
AsynchronousServerSocketChannel 类的对象指定侦听传入客户端连接请求的套接字服务器。只有在接受请求后才能开始交互。名为 AsynchronousSocketChannel 的类负责客户端和服务器两端的所有建立交互。
普通的,也就是同步套接字连接和异步套接字连接之间的主要区别在于,在后一种情况下,请求者会在每个操作完成后立即得到通知。同步套接字连接不是这种情况,因为在这种情况下,它会阻塞通道,直到请求完成。
由于套接字通道的异步特性,有一个处理程序负责处理套接字操作的成功或失败状态。
发表评论 取消回复