保持Java套接字打开 - 如何检查新数据是否可用?

时间:2014-10-03 23:06:34

标签: java sockets

我有一个简单的客户端 - 服务器应用程序,使用套接字进行通信。一种可能性是每次客户端向服务器发送内容时关闭套接字。

但我的想法是保持连接始终打开,即如果客户端联系服务器,连接应该放入队列(例如LinkedBlockingQueue)并保持打开状态,这将提高性能。

如果队列中的套接字中有新数据,我该如何检查服务器?我唯一可以想象的是不断迭代整个队列并检查每个套接字是否有新数据。但这样效率非常低,因为如果我有几个线程在队列上工作,当一个线程扫描队列时,队列就会被阻塞。

或者是否有可能在套接字上注册回调函数,以便套接字通知线程数据已准备就绪?

2 个答案:

答案 0 :(得分:2)

  

但我的想法是保持连接始终打开,即如果客户端联系服务器,连接应该放入队列(例如LinkedBlockingQueue)并保持打开状态,这将提高性能。

保持连接打开会提高性能,但存在扩展问题:打开的套接字使用内核资源。 (我不会使用队列......)

  

如果队列中的套接字中有新数据,我该如何检查服务器?

如果您有多个套接字连接到不同的客户端,并且您希望以(大致)它到达的顺序处理数据,则有两种常用技术:

  • 为每个套接字创建一个线程,让每个线程只读一次。这将(自然地)阻止线程,直到数据可用。

  • 使用NIO通道选择器机制(参见Selector),它可以让您找出一组I / O通道中哪一个可以进行读取或写入。

每个套接字的线程往往是资源匮乏(线程堆栈),并且如果您有多个同时处于活动状态的线程,则根本不能很好地扩展。 (上下文切换太多,线程调度程序负载过多。)

相比之下,选择器映射到主机操作系统提供的本机系统调用,因此它们是高效且响应迅速的......如果智能使用的话。

(您还可以获得套接字的非阻塞通道,并以循环方式轮询它们。但这不会有效或响应。)

正如您所看到的,这些想法都不适用于队列。你有多个线程处理一个套接字,或者你有一个线程处理数组或(数组)套接字列表。队列抽象不是为索引或迭代而设计的。

  

或者是否有可能在套接字上注册回调函数,以便套接字通知线程数据已准备就绪?

请参阅@ Lolo的回答。

答案 1 :(得分:0)

一个实际的解决方案是使用NIO2 AsynchronousSocketChannel来执行异步读取操作,并使用您可以指定为CompletionHandler的回调。