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

问题描述 投票:6回答:4

我试图从Android中的客户端读取服务器套接字中的数据。

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

客户端(在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;
            }
    }

服务器(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

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

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

我得到的错误是:

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.access$100(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

我知道这有点令人困惑。 Python代码还没有由我编写,并且存在一个没有任何错误的python客户端。我只在我的JAVA代码中收到此错误。

使用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)

如果您需要更多信息,请与我们联系。

谢谢。

java android python sockets socketexception
4个回答
1
投票

如果你正在使用setChunkedStreamingMode然后删除它然后看。我想我已经这么晚了但这解决了我的问题。你可以使用固定长度流模式。


1
投票

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


0
投票

也许我对你的问题遗漏了一点,但我认为使用这个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();
    }
}

希望这可以帮助...


0
投票

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

也是isConnected() - 哑测试,因为它永远是真的。

© www.soinside.com 2019 - 2024. All rights reserved.