Java 套接字——异步等待,同步读取
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/959785/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java sockets - asynchronous wait, synchronous read
提问by hmp
I want to be able to asynchronously wait on a socket, then synchronously read from it:
我希望能够异步等待套接字,然后同步读取它:
for (;;)
{
while (data available on socket)
{
read message from socket;
process it;
}
do something else;
}
I need this because I want to poll a queue with messages from GUI at the same time, so the "do something else" part has a short wait().
我需要这个是因为我想同时使用来自 GUI 的消息轮询队列,所以“做其他事情”部分有一个简短的wait().
Is this possible with Java sockets? I tried to check .available()on a DataInputStreamassociated with the socket, but
这可以用 Java 套接字实现吗?我试图检查与套接字关联的.available()一个DataInputStream,但是
- It seems to work only when I connect, not when I accept a connection (???)
- I get no indication that the connection has been closed.
- 它似乎只有在我连接时才有效,在我接受连接时无效 (???)
- 我没有得到连接已关闭的迹象。
I tried to do it with a Selector, but it requires the socket channel to be in non-blocking mode all the time.
我尝试使用 Selector 来完成它,但它要求套接字通道始终处于非阻塞模式。
回答by Yuval Adam
回答by objects
Why don't you use two threads (or am I misunderstanding what you want to do)?
你为什么不使用两个线程(或者我误解了你想要做什么)?
回答by Ribo
The 'available()' method of InputStream from the Socket will tell you if there is data available on the socket before you call the blocking read() method.
来自 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;
}
Don't call the blocking read if there is no data to read. Don't block reading more data than is available at the time.
如果没有要读取的数据,请不要调用阻塞读取。不要阻止读取超过当时可用的数据。
A related method of interest (but not for your specific need) is sock.setSoTimeout(millis) this call allows you to call a sock.read(...) and have it wait for at most a specific amount of time before it throws an exception (that you would handle) or that returns data. This is useful if you want expect a prompt response but want to handle issues where a server may no longer be responding.
感兴趣的相关方法(但不是针对您的特定需要)是 sock.setSoTimeout(millis) 此调用允许您调用 sock.read(...) 并让它在抛出之前最多等待特定的时间异常(您将处理)或返回数据。如果您希望得到快速响应,但又想处理服务器可能不再响应的问题,这将非常有用。
Another issue is that you put the one curly brackets on the wrong line, when everyone knows they belong on end of the if/while/for statement :-)
另一个问题是,当每个人都知道它们属于 if/while/for 语句的末尾时,您将一个大括号放在了错误的行上:-)
回答by caskey
In sockets programming the data may come in as arbitrary chunks depending upon the interaction between the sending system, intermediate links and how your OS treats PSH flags. You'll need to put a BufferedInputStream in the middle and make use of the available() method and push back bytes until you have a complete "message" which you can then process.
在套接字编程中,数据可能以任意块的形式出现,具体取决于发送系统、中间链接和操作系统如何处理 PSH 标志之间的交互。您需要在中间放置一个 BufferedInputStream 并使用 available() 方法并推回字节,直到您拥有完整的“消息”,然后您才能对其进行处理。
The correct java solution involves making your own MessageInputStream which wraps a BufferedInputStream and provides similar available() functionality which tells the caller how many messages are immediately available for reading.
正确的 java 解决方案涉及制作您自己的 MessageInputStream,它包装 BufferedInputStream 并提供类似的 available() 功能,该功能告诉调用者有多少消息可以立即读取。
回答by Reginaldo
I'd do
我会做
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);
}
}
}

