java.net.SocketException: sendto failed: EPIPE (Broken pipe) on Android

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23357479/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:11:09  来源:igfitidea点击:

java.net.SocketException: sendto failed: EPIPE (Broken pipe) on Android

javaandroidpythonsocketssocketexception

提问by Rajesh Golani

I am trying to read data from server socket from client in Android.

我正在尝试从 Android 客户端从服务器套接字读取数据。

Here are the snippets of code that I'm using:

以下是我正在使用的代码片段:

Client(On Android in JAVA)

客户端(在 JAVA 中的 Android 上)

    DataOutputStream dataOutputStream = null;
    DataInputStream dataInputStream = null;
    try {

        if (client.socket == null || !client.socket.isConnected())
            client.createSocket();

        // Get Input/Output stream for socket
        dataOutputStream = new DataOutputStream(client.socket.getOutputStream());
        dataInputStream = new DataInputStream(client.socket.getInputStream());

       // Here RS is simple JAVA class that stores information about payload and response length
        Log.d("Send", "Sending payload for pair " + RS.getc_s_pair() + " " + RS.getResponse_len());

        dataOutputStream.write(UtilsManager.serialize(RS.getPayload()));

        // Notify waiting Queue thread to start processing next packet
        if (RS.getResponse_len() > 0) {
            Log.d("Response", "Waiting for response for pair " + RS.getc_s_pair() + " of " + RS.getResponse_len() + " bytes");

            int totalRead = 0;

            byte[] buffer = new byte[RS.getResponse_len()];
            while (totalRead < RS.getResponse_len()) {
                int bytesRead = dataInputStream.read(buffer, totalRead, RS.getResponse_len() - totalRead);

                if (bytesRead < 0) {
                    throw new IOException("Data stream ended prematurely");
                }
                totalRead += bytesRead;
            }
    }

Server (Python)

服务器 (Python)

        # Here request_len is the expected request size
        while buffer_len < response_set.request_len:
            new_data = connection.recv( min(self.buff_size, response_set.request_len-buffer_len) )
            if not new_data:
                return False
            buffer_len += len(new_data)

        # Send required response
        for response in response_set.response_list:
            try:
                connection.sendall(str(response.payload))
            except:
                return False

Sometimes, I am getting error while I'm sending payload from client on line

有时,当我从客户端在线发送有效负载时出现错误

       dataOutputStream.write(UtilsManager.serialize(RS.getPayload()));

Error I'm getting is:

我得到的错误是:

java.net.SocketException: sendto failed: EPIPE (Broken pipe)
    at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:506)
    at libcore.io.IoBridge.sendto(IoBridge.java:475)
    at java.net.PlainSocketImpl.write(PlainSocketImpl.java:507)
    at java.net.PlainSocketImpl.access0(PlainSocketImpl.java:46)
    at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:269)
    at java.io.DataOutputStream.write(DataOutputStream.java:98)
    at java.io.OutputStream.write(OutputStream.java:82)
    at com.rgolani.replay.tcp.TCPClientThread.run(TCPClientThread.java:56)
    at java.lang.Thread.run(Thread.java:856)
Caused by: libcore.io.ErrnoException: sendto failed: EPIPE (Broken pipe)
    at libcore.io.Posix.sendtoBytes(Native Method)
    at libcore.io.Posix.sendto(Posix.java:151)
    at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:177)
    at libcore.io.IoBridge.sendto(IoBridge.java:473)
    ... 7 more

I know this is little bit confusing. Python code has not been written by me and there exists a python client which works without any errors. I'm getting this error only in my JAVA code.

我知道这有点令人困惑。Python 代码不是我写的,并且存在一个可以正常工作的 Python 客户端。我只在我的 JAVA 代码中收到此错误。

Working Python Client

工作 Python 客户端

    if self.sock is None:
        self._connect_socket()

    self.sock.sendall(tcp.payload)

    buffer_len = 0
    while tcp.response_len > buffer_len:
        data = self.sock.recv( min(self.buff_size, tcp.response_len-buffer_len) )
        buffer_len += len(data)

Please let me know if you need more information.

如果您需要更多信息,请告诉我。

Thank you.

谢谢你。

回答by Yvan781

Maybe i am missing a point with your issue, but i think it would be nicer to use this Java snippet:

也许我在您的问题中遗漏了一点,但我认为使用此 Java 代码段会更好:

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;

ObjectOutputStream dataOutputStream = null;
ObjectInputStream dataInputStream = null;
try {

    if (client.socket == null || !client.socket.isConnected())
        client.createSocket();

    // Get Input/Output stream for socket
    dataOutputStream = new ObjectOutputStream (client.socket.getOutputStream());
    dataInputStream = new ObjectInputStream (client.socket.getInputStream());

    // Here RS is simple JAVA class that stores information about payload and response length
    Log.d("Send", "Sending payload for pair " + RS.getc_s_pair() + " " + RS.getResponse_len());

    // You might consider using java.io.Serializable interface with the argument object
    dataOutputStream.writeObject(UtilsManager.serialize(RS.getPayload()));

    // Notify waiting Queue thread to start processing next packet
    if (RS.getResponse_len() > 0) {
        Log.d("Response", "Waiting for response for pair " + RS.getc_s_pair() + " of " + RS.getResponse_len() + " bytes");

        // Read a java.io.Serializable object from the stream. So you have to write a java.io.Serializable object into the stream.
        Object o = dataInputStream.readObject();
    }
}

Hope this helps...

希望这可以帮助...

回答by Sumit Joshi

If you are using setChunkedStreamingModethen remove it and then see.I think I am so late but this solves my problem.You can use fixed length streaming mode.

如果您正在使用,setChunkedStreamingMode则将其删除然后查看。我想我来得太晚了,但这解决了我的问题。您可以使用固定长度的流模式。

回答by bardi

That error occurs when the client try to write to a connection when the backend has already closed it. By default Android set the Keep Aliveproperty to true and will reuse the old socket connections since establishing a connection is a resource consuming operation in a mobile environment (you can test it with a tool like fiddler). Try to set the Connectionheader to closeor call System.setProperty("http.keepAlive", "false");in order to disable Keep Alive and thus forcing the system to create a new connection.

当后端已经关闭连接时客户端尝试写入连接时会发生该错误。默认情况下,Android 将该Keep Alive属性设置为 true 并将重用旧的套接字连接,因为在移动环境中建立连接是一项资源消耗操作(您可以使用类似fiddler的工具对其进行测试)。尝试将Connection标头设置为closeor callSystem.setProperty("http.keepAlive", "false");以禁用 Keep Alive,从而强制系统创建新连接。

回答by Alexey Kurilov

In my case: client.createSocket(); don't connect to any server - just create a socket. So later I must client.connect(_sock_sddr_here_);

就我而言:client.createSocket(); 不要连接到任何服务器 - 只需创建一个套接字。所以后来我必须 client.connect(_sock_sddr_here_);

Also isConnected() - dumb test because it's forever true.

还有 isConnected() - 愚蠢的测试,因为它永远是真的。