【问题标题】:java.net.SocketException: sendto failed: EPIPE (Broken pipe) on Androidjava.net.SocketException: sendto failed: Android 上的 EPIPE (Broken pipe)
【发布时间】:2014-06-14 23:12:31
【问题描述】:

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

这是我正在使用的代码的 sn-ps:

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


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 我使用 setChunkedStreamingMode 因为 link 。并且遇到过一次。它是服务器的 php 不允许非固定长度。应该在服务器端解决,不需要在客户端删除代码。
      【解决方案4】:

      也许我在你的问题上遗漏了一点,但我认为使用这个 Java sn-p 会更好:

      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();
          }
      }
      

      希望这会有所帮助...

      【讨论】:

        猜你喜欢
        • 2013-01-15
        • 1970-01-01
        • 2013-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多