IOException:断管

Posted

技术标签:

【中文标题】IOException:断管【英文标题】:IOException: Broken pipe 【发布时间】:2017-06-12 08:00:33 【问题描述】:

我正在实现与 android 应用程序通信的服务器端应用程序。安卓应用 之前已经实现了,原来是和 C++ Server 通信的。现在我想用 java 代码替换 C++ 服务器。 Android 应用程序与服务器通信以在读卡器中通过他的卡对人进行身份验证。

身份验证协议包含应用程序和服务器之间要成功完成的通信的多个步骤。

应用程序和服务器之间的消息具有以下形式:

<type> 0x00 0x00 0x00 <length> 0x00 0x00 0x00 [<data>]
    首先,应用程序发送类型 1 的请求以建立与读卡器中的 sim 卡的连接。 然后服务器上的 clientSocket 发送一个类型为 0 的响应,该响应头已收到最后一条消息。 之后,服务器收到类型 2 的新请求,将 sim 卡的 ATR(Answer To Rest)发送到应用程序。 服务器的clientSocket向应用发送类型2的消息。 . . . . . . . . . . . . .

最后我想关闭服务端的clientSocket和serverSocket。

我已经添加了重要的代码:

import java.io.BufferedInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.Arrays;


public class Test 

    private final static int RECEIVE_BUFFER_LENGTH = 512;
    public final static int MESSAGE_MAXIMUM_LENGTH = 256;
    private final static int MESSAGE_HEADER_LENGTH = 8;


    public static void main(String args[]) throws Exception 
        ServerSocket serverSocket = new ServerSocket(3003);
        while (true) 
            Socket clientSocket = serverSocket.accept();
            ByteBuffer receiveBuffer = ByteBuffer.allocate(Test.RECEIVE_BUFFER_LENGTH);
            int readBytes = 0;
            InputStream bufferedInputStream = new BufferedInputStream(clientSocket.getInputStream());
            while (true) 
                ByteBuffer answerBuffer = null;
                readBytes = bufferedInputStream.read(receiveBuffer.array(), receiveBuffer.position(),
                        receiveBuffer.remaining());
                System.out.println("readBytes: " + readBytes); // Here I am getting 9 then -1.
                if (readBytes < 0) 
                    break;
                
                // Here I am processing the message.
                // .......
                // after ending the processing send a reponse to the Android app.

                try 
                    answerBuffer = ByteBuffer.allocate(Test.MESSAGE_HEADER_LENGTH);
                    answerBuffer.put((byte) 0x00); // at position 0
                    DataOutputStream dOut = new DataOutputStream(clientSocket.getOutputStream());
                    dOut.writeBytes(Arrays.toString(answerBuffer.array()));
                    dOut.flush();
                 catch (IOException e) 
                    e.printStackTrace();
                
                System.out.println("The sent answer to the client:  " + Arrays.toString(answerBuffer.array()));
            

        
    


输出:

readBytes: 9
The sent answer to the client:  [0, 0, 0, 0, 0, 0, 0, 0]
readBytes: -1

错误 我在 android 应用程序中收到以下错误:

IOException: 损坏的管道

【问题讨论】:

【参考方案1】:

你在这里是从一个鼹鼠山变成一座山。这是一个简单的方法:

Socket clientSocket = serverSocket.accept();
byte[] receiveBuffer = new byte[Test.RECEIVE_BUFFER_LENGTH];
InputStream bufferedInputStream = new BufferedInputStream(clientSocket.getInputStream());
while (true) 
    int readBytes = bufferedInputStream.read(receiveBuffer);
    System.out.println("readBytes: " + readBytes); // Here I am getting 9 then -1.
    if (readBytes < 0) 
        break;
    
    // Here you need to process `receiveBuffer[0..readBytes-1],
    //  and note that it may not contain a complete message,
    // so you may have to do more reading.
    // ...
    // after ending the processing send a reponse to the Android app.

    try 
        byte[]    answerBuffer = 0x00;
        clientSocket.getOutputStream().write(answerBuffer);
        System.out.println("Sent answer to the client");
     catch (IOException e) 
            e.printStackTrace();
    

clientSocket.close();

目前您正在发送完整的垃圾邮件,因为ByteBuffers 的所有毫无意义和不正确的搞砸。

但是如果正确:

<type> 0x00 0x00 0x00 <length> 0x00 0x00 0x00 [<data>]

你没有发送它。类型 0 的正确消息肯定是这样的:

0x00 0x00 0x000 0x000 0x00 0x00 0x00

前三个字节是类型,后三个字节是数据长度,显然是零。在看起来像这样的代码中:

byte[] answerBuffer = 0,0,0,0,0,0;

【讨论】:

但在这种情况下,如果 InputStream 中没有数据并且我无法再与应用程序通信,则 clientSocket 将被关闭?或者我遗漏了一些东西,bufferedInputStream 总是有来自应用程序的数据,如果应用程序没有发送数据,那么 readBytes 值是-1?目前使用您的代码,我遇到了同样的错误。我刚刚发送了 8 个字节。我不需要在这里使用flush()吗? 没有。 Socket.getInputStream() 不需要刷新,如果对等方已经关闭连接,则客户端套接字正在关闭。这就是 read() 返回 -1 的含义。如果对端已经关闭了连接,你就不能写入它,因为它已经不存在了。

以上是关于IOException:断管的主要内容,如果未能解决你的问题,请参考以下文章

IOException - 使用 FileOutputStream 拒绝访问

如何同时处理 IOException 和 IIOException

解决Caused by: java.io.IOException: java.io.IOException: error=12, Cannot allocate memory

不可捕获的 IOException

写入 CSV 文件:IOException:流已关闭

React Native:错误:[消息/未知] java.io.IOException:java.util.concurrent.ExecutionException:java.io.IOExcept