【问题标题】:Keeping java sockets open - how to check if new data available?保持 Java 套接字打开 - 如何检查新数据是否可用?
【发布时间】:2014-10-04 07:35:17
【问题描述】:

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

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

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

或者有没有可能在socket上注册一个回调函数,让socket通知线程数据准备好了?

【问题讨论】:

  • socket 的 InputStreams 有几个读方法会阻塞当前线程,直到有东西可用。你通常需要做套接字网络多线程。这意味着每个客户端都有一个接收线程,将数据存储在主线程可以在需要时检索它的地方。 (评论因为不确定这是否是问题)

标签: java sockets


【解决方案1】:

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

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

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

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

  • 为每个套接字创建一个线程,并让每个线程简单地进行读取。这将(自然)阻塞线程,直到数据可用。

  • 使用 NIO 通道选择器机制(请参阅 Selector),它允许您找出一组 I/O 通道中的哪一个已准备好进行读取或写入。

每个套接字的线程往往会占用大量资源(线程堆栈),并且如果您有多个同时处于活动状态的线程,则根本无法很好地扩展。 (上下文切换过多,线程调度程序的负载过大。)

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

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

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

或者有没有可能在socket上注册一个回调函数,让socket通知线程数据准备好了?

查看@Lolo 的回答。

【讨论】:

  • 感谢您的回答。假设我有一个线程,它是在套接字线程接受连接时创建的。当线程现在将连接放入队列然后线程终止时,这是否也会关闭连接?
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2012-11-23
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多