简体   繁体   English

java 套接字输出流和损坏 pipe

[英]java socket outputstream and broken pipe

I have to send a dynamic buffer size to the socket stream. It works correctly, but when I try to send multiple buffers with a size bigger than int my_buffer_size =18 * 1024 ;我必须向套接字 stream 发送动态缓冲区大小。它工作正常,但是当我尝试发送大小大于int my_buffer_size =18 * 1024的多个缓冲区时; (this is an indicative value) (这是一个指示值)

I get the error (for some write):我收到错误(对于某些写入):

Java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)

My code is very simple: For example If I want to send a big file I read a file stream with我的代码非常简单:例如,如果我想发送一个大文件,我会读取一个文件 stream

byte[] bs = new byte[my_buffer_size];
while (... ){ 
fileInputStream.read(bs);
byte[] myBufferToSend = new byte[sizeBuffer];
DataOutputStream out = new DataOutputStream(cclient.getoutputStream());
out.writeInt(myBufferToSend.length);
out.write(myBufferToSend);
out.flush();
}

(The file is just a test the buffer size can be variable) (该文件只是一个测试,缓冲区大小可以是可变的)

the SendBufferSize is 146988. SendBufferSize 是 146988。

Is there a way to fix the broken pipe error?有没有办法修复损坏的 pipe 错误? I read around but actually I didn't solve the problem.我四处阅读,但实际上我没有解决问题。

Thank you any help is appreciated谢谢任何帮助表示赞赏

I use the classic ServerSocket serverSocket;我使用经典的 ServerSocket serverSocket; and Socket cclient和套接字客户端

'Broken pipe' means that you've written data to a connection that has already been closed by the other end. “断管”表示您已将数据写入已被另一端关闭的连接。

Ergo the problem lies at the other end, not in this code. 问题在于另一端,而不是在此代码中。 Possibly the other end doesn't really understand your length-word protocol for example, or doesn't implement it correctly. 可能另一端并不真正理解你的长字协议,或者没有正确实现它。

If it's anything like this code it won't, because you're ignoring the result returned by read() and assuming that it fills the buffer. 如果它与此代码类似,则不会,因为您忽略了read()返回的结果并假设它填充了缓冲区。 It isn't specified to do that, only to transfer at least one byte. 没有指定这样做,只传输至少一个字节。

In common, receiving huge blocks is not supported by DataInputStream , because the read method just delegates to the underlying socket input stream and that socket input stream does not complain about not having read all.通常, DataInputStream不支持接收大块,因为read方法只是委托给底层套接字输入 stream,而套接字输入 stream 不会抱怨没有读取全部。 Eg in Oracle Java 8 you get some 2^16 bytes and the rest is ignored.例如,在 Oracle Java 8 中,您会得到一些 2^16 字节,而 rest 将被忽略。 So when you close the socket after DataInputStream.read has returned, the sender node observes a "pipe broken" while still trying the send the rest of the huge block.因此,当您在DataInputStream.read返回后关闭套接字时,发送方节点观察到“管道损坏”,同时仍在尝试发送巨大块的 rest。 Solution is a windowed read.解决方案是窗口阅读。 Below is a DataInputStream -subclass, which does precisely this.下面是一个DataInputStream子类,它正是这样做的。

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;

public class HugeDataInputStream extends DataInputStream
{
    int maxBlockLength;

    public HugeDataInputStream(InputStream in)
    {
        this(in, 0x8000);
    }

    public HugeDataInputStream(InputStream in, int maxBlockLength)
    {
        super(in);
        this.maxBlockLength = maxBlockLength;
    }

    public int readHuge(byte[] block) throws IOException
    {
        int n = block.length;
        if (n > maxBlockLength)
        {
            int cr = 0;
            while (cr < n)
            {
                cr += super.read(block, cr, Math.min(n - cr, maxBlockLength));
            }
            return cr;
        }
        else
        {
            return super.read(block);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM