Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 插座与插座通道_Java_Sockets_Socketchannel - Fatal编程技术网

Java 插座与插座通道

Java 插座与插座通道,java,sockets,socketchannel,Java,Sockets,Socketchannel,我试着去理解,总的来说。我知道如何使用常规套接字,以及如何为每个客户机服务器创建一个简单线程(使用常规阻塞套接字) 所以我的问题是: 什么是袜子通道 当我使用SocketChannel而不是Socket时,额外得到了什么 通道和缓冲区之间的关系是什么 什么是选择器 中的第一个信号是面向流的连接插座的可选通道。。这是什么意思 我也读过了,但不知怎么的,我没有读到…一个套接字是一个阻塞输入/输出设备。它使使用它阻止读取的线程,如果底层缓冲区已满,则还可能阻止写入。因此,如果服务器有一堆打开的So

我试着去理解,总的来说。我知道如何使用常规套接字,以及如何为每个客户机服务器创建一个简单线程(使用常规阻塞套接字)

所以我的问题是:

  • 什么是袜子通道
  • 当我使用SocketChannel而不是Socket时,额外得到了什么
  • 通道和缓冲区之间的关系是什么
  • 什么是选择器
  • 中的第一个信号是面向流的连接插座的可选通道。。这是什么意思

我也读过了,但不知怎么的,我没有读到…

一个
套接字
是一个阻塞输入/输出设备。它使使用它阻止读取的
线程
,如果底层缓冲区已满,则还可能阻止写入。因此,如果服务器有一堆打开的
Socket
s,则必须创建一堆不同的线程


SocketChannel
是一种从套接字读取数据的非阻塞方式,因此您可以让一个线程同时与一组打开的连接通信。这是通过将一组
SocketChannel
添加到
选择器
,然后在选择器的
select()
方法上循环来实现的,该方法可以通知您套接字是否已被接受、接收到数据或已关闭。这允许您在一个线程中与多个客户端通信,而不需要多线程和同步的开销


Buffer
s是NIO的另一项功能,它允许您通过读写操作访问底层数据,以避免将数据复制到新数组的开销。

到现在为止
NIO
已经很老了,很少有人记得1.4之前的Java是什么样子,这是理解“为什么”需要知道的属于
NIO

简而言之,直到Java1.3,所有I/O都是阻塞类型的。更糟糕的是,没有类似于
select()
系统调用的多路I/O。因此,用Java实现的服务器别无选择,只能采用“每个连接一个线程”的服务策略

Java 1.4中引入的NIO的基本要点是使传统UNIX风格的多路复用非阻塞I/O功能在Java中可用。如果您了解如何使用
select()
poll()
编程来检测一组文件描述符(通常是套接字)上的I/O就绪情况,那么您将在
NIO
中找到所需的服务:您将使用
SocketChannel
来检测非阻塞I/O端点,和用于FDSET或pollfd数组的选择器。现在,具有线程池或每个线程处理多个连接的服务器成为可能。这是“额外的”


缓冲区是非阻塞套接字I/O所需的字节数组,尤其是在输出/写入端。如果只能立即写入缓冲区的一部分,那么通过阻塞I/O,您的线程将只是阻塞,直到可以写入整个缓冲区。使用非阻塞I/O时,线程会得到一个返回值,返回值为写了多少,剩下的留给您处理,以备下一轮使用。
缓冲区
通过显式实现生产者/消费者填充和排出模式来处理这些机械细节,可以理解,线程和JVM的内核将不同步

即使您使用的是
SocketChannels
,也必须使用线程池来处理
通道


考虑到场景,如果一个通道的处理时间为1秒,且队列中有10个通道,则只使用一个线程,负责轮询
select()
和处理从
选择器中选择的
SocketChannels
,这意味着你必须在下次投票前等待10秒,这是无法忍受的。因此,应该有一个用于通道处理的线程池

从这个意义上讲,我看不出每客户端线程阻塞套接字模式有多大区别。主要区别在于
NIO
模式,任务更小,更像是每个任务的线程,任务可以读、写、业务流程等。更多细节,您可以看看Netty实现的
NioServerSocketChannelFactory
,它使用一个Boss线程接受连接,并将任务分派到工作线程池中进行处理

如果你真的喜欢一个线程,底线是至少你应该有池I/O线程,因为I/O操作通常比指令处理周期慢很多,你不会希望宝贵的一个线程被I/O阻塞,而这正是NodeJS所做的,使用一个线程接受连接,所有I/O都是异步的,并且由后端I/O线程池并行处理

每个客户端的旧式线程是否已死亡?
我不这么认为,NIO编程很复杂,多线程也不是天生的邪恶,请记住,现代操作系统和CPU越来越擅长多任务处理,因此,随着时间的推移,多线程的开销会越来越小。

我必须为那些因为背景而不是内容而对你的问题投了否决票的人道歉。作为一名研究生,我完全理解当你被迫攻读一门不属于你研究领域的课程时,尤其是当你的资金依赖于它时。我认为你来这里寻求澄清也很好。非常感谢。但我还是有一些遗漏。使用没有选择器的频道有什么好处吗?或者它们一起使用?如果没有选择器,则不能使用频道,因为选择器会告诉您何时可以读取频道。我想不出你为什么要自己使用频道,因为你基本上是在重新实现选择器的功能