Java套接字 - 异步等待,同步读取

时间:2009-06-06 14:20:20

标签: java sockets

我希望能够异步等待套接字,然后同步读取它:

for (;;) 
{
    while (data available on socket) 
    {
        read message from socket;
        process it;
    }
    do something else;
}

我需要这个,因为我想同时使用来自GUI的消息轮询队列,所以“做其他事情”部分有一个简短的wait()

Java套接字可以实现吗?我尝试检查与套接字关联的.available()上的DataInputStream,但

  • 它似乎仅在我连接时起作用,而不是在我接受连接时(???)
  • 我没有表明连接已经关闭。

我尝试使用Selector,但它要求套接字通道始终处于非阻塞模式。

5 个答案:

答案 0 :(得分:5)

Java非阻塞I / O包(java.nio)允许您通过Selector从套接字进行异步读取。

检查this link以获取一些示例以帮助您入门。

答案 1 :(得分:2)

为什么不使用两个线程(或者我误解了你想做什么)?

答案 2 :(得分:2)

来自Socket的InputStream的'available()'方法将告诉您在调用阻塞的read()方法之前套接字上是否有可用的数据。

InputStream sockIS = sock.getInputStream();
int ba;  // Number of bytes available to read from socket
for (;;) {
    while ((ba = sockIS.available()) > 0) {
        read message from socket;
        process it;
    }
    do something else;
}

如果没有要读取的数据,请不要调用阻塞读取。不要阻止阅读比当时更多的数据。

感兴趣的相关方法(但不是针对您的特定需求)是sock.setSoTimeout(millis)此调用允许您调用sock.read(...)并让它等待最多一段特定的时间在它抛出异常(您将处理)或返回数据之前。如果您希望获得快速响应但希望处理服务器可能不再响应的问题,这将非常有用。

另一个问题是你把一个大括号放在错误的行上,当每个人都知道它们属于if / while / for语句的末尾时: - )

答案 3 :(得分:0)

在套接字编程中,数据可以作为任意块进入,具体取决于发送系统,中间链接以及操作系统如何处理PSH标记之间的交互。您需要在中间放置一个BufferedInputStream并使用available()方法并推回字节,直到您有一个完整的“消息”,然后您可以处理它。

正确的java解决方案包括创建自己的MessageInputStream,它包装BufferedInputStream并提供类似的available()功能,告诉调用者有多少消息可以立即读取。

答案 4 :(得分:0)

我会做

public class MainClass extends WhateverSuperClass implements WhateverInterface { 
// . . .

  private Listener listener;

  public MainClass() {
    listener = new Listener(this);
  }

  public void theMethod(){
    //do something else
  }
}

public class Listener extends Thread {
  public Listener(MainClass clazz) {

    // initialize thread resources (sockets, database connections, etc)
    start();
    Thread.yield();
  }

  public void run() {
    for (;;) 
    {
      // there's no need to test if there is 
      // data available on socket, since this
      // loop runs in a separate thread

      // read message from socket;
      // clazz.process(message);
    }
  }
}