Java:正确的网络IO处理?

时间:2010-03-01 03:33:22

标签: java network-programming io

我遇到的问题是,当我使用InputStream读取字节时,它会一直阻塞,直到连接完成。 EG:

        InputStream is = socket.getInputStream();
        byte[] buffer = new byte[20000];
        while (is.read(buffer) != -1) {
            System.out.println("reading");
        }
        System.out.println("socket read");

“套接字读取”在实际收到FYN数据包之前不会打印出来,从而关闭连接。在没有阻塞的情况下接收所有字节并等待连接丢弃的正确方法是什么?

6 个答案:

答案 0 :(得分:2)

查看java.nio支持non-blocking IO的内容。

答案 1 :(得分:2)

对于传统的套接字,重点是通常你希望它们阻止:你在逻辑上做什么,你不希望你的程序阻塞是你把你的读/写代码放在另一个线程,以便单独的读/写线程阻塞,但不是整个程序。

如果失败,你可以使用available()方法在阅读之前查看是否有任何可用的输入。但是,你需要注意不要通过不断调用available()来坐在循环中燃烧CPU。

编辑:如果问题是你很高兴在字节到达之前阻止,但是直到连接断开(这就是正在发生的事情),那么你需要制作另一端的客户端在发送字节后在其输出流上调用flush()。

答案 2 :(得分:2)

阅读直到你得到-1 意味着你想要阅读直到EOS。如果您不想在EOS之前阅读,请不要循环直到-1:更快停止。问题是'什么时候?'

如果您想要阅读完整的“消息”而不再阅读,则必须以读者可以找到其结尾的方式发送消息:例如,类型 - 长度 - 值协议,或更简单的大小每条消息之前的单词,或XML等自描述协议。

答案 3 :(得分:1)

取自exampledepot on java.nio

的示例
// Create a direct buffer to get bytes from socket.
// Direct buffers should be long-lived and be reused as much as possible.
ByteBuffer buf = ByteBuffer.allocateDirect(1024);

try {
    // Clear the buffer and read bytes from socket
    buf.clear();
    int numBytesRead = socketChannel.read(buf);

    if (numBytesRead == -1) {
        // No more bytes can be read from the channel
        socketChannel.close();
    } else {
        // To read the bytes, flip the buffer
        buf.flip();

        // Read the bytes from the buffer ...;
        // see Getting Bytes from a ByteBuffer
    }
} catch (IOException e) {
    // Connection may have been closed
}

请务必了解缓冲区翻转,因为它会引起很多麻烦。基本上,您必须反转缓冲区才能从中读取。如果要重用该缓冲区以使套接字写入其中,则必须再次翻转它。但是clear()会重置缓冲区方向。

答案 4 :(得分:1)

试试这个:

        InputStream is = socket.getInputStream();
        byte[] buffer = new byte[20000];
        int bytesRead;
        do {
            System.out.println("reading");
            bytesRead = is.read(buffer);
        }
        while (is.available() > 0 && bytesRead != -1);
        System.out.println("socket read");

更多信息:http://java.sun.com/j2se/1.4.2/docs/api/java/io/InputStream.html#available()

答案 5 :(得分:1)

代码可能没有按照您的想法执行。 read(buffer)返回它读取的字节数,换句话说:无论如何都不保证填满你的缓冲区。 有关填满整个数组的代码,请参阅DataInputStream.readFully():

或者您可以使用此函数(基于DataInputStream.readFully()):

public final void readFully(InputStream in, byte b[]) throws IOException
{
    readFully(in, b, 0, b.length);
}

public final void readFully(InputStream in, byte b[], int off, int len) throws IOException
{
    if (len < 0) throw new IndexOutOfBoundsException();
    int n = 0;
    while (n < len)
    {
        int count = in.read(b, off + n, len - n);
        if (count < 0) throw new EOFException();
        n += count;
    }
}

您的代码如下:

InputStream is = socket.getInputStream();
byte[] buffer = new byte[20000];
readFully(is, buffer);
System.out.println("socket read");