从Socket读取的Android在第二个读取循环中挂起

时间:2012-11-19 11:52:25

标签: java android sockets inputstream

我必须在我的应用程序中实现聊天。使用套接字连接到服务器。我应该注册到该服务器,服务器将通过回复知道。

我已经在一个方法中使用BufferedWriter发送命令,然后从输入流开始读取,直到它告诉我没有更多数据。

我正确阅读了服务器回复。但是,我从来没有从第二个in.read调用中获得负值,因此我的方法在while循环中保持阻塞(在我进行该调用的conditionnal语句中)。

如何使用套接字完成此操作?我通常使用文件或其他输入流来做到这一点。

如果我只读取我应该阅读的字节,那是否意味着我要么:

  • 事先知道服务器响应的长度吗?
  • 或让服务器发送代码通知它已完成发送响应?

目前我正在做以下事情:

private String sendSocketRequest(String request, boolean skipResponse) throws ChatException {
    if (!isConnected()) openConnection();

    try {
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
                                     socket.getOutputStream()), 2048);
        out.append(request);
        out.flush();
        out = null;
    } catch (IOException e) {
        LogHelper.error("Unable to send socket request: " + request, e);
        throw new ChatException("Unable to send socket request: " + request, e);
    }

    try {
        BufferedReader in = new BufferedReader(new InputStreamReader(
                                     socket.getInputStream()), 2048);
        StringBuffer response = new StringBuffer();
        char[] buffer = new char[2048];
        int charsRead = -1;

// >>>>>>>> This is where it gets blocked <<<<<<<<<

        while ((charsRead = in.read(buffer)) >= 0) {
            if (charsRead > 0) response.append(new String(buffer, 0, charsRead));
        }
        return response.toString();
    } catch (IOException e) {
        LogHelper.error("Unable to read socket response: " + request, e);
        throw new ChatException("Unable to read socket response: " + request, e);
    }
}

使用以下方法连接服务器:

public synchronized void openConnection() throws ChatException {
    try {
        socket = new Socket(Constants.API_CHAT_SERVER_ADDRESS, Constants.API_CHAT_SERVER_PORT);
        socket.setKeepAlive(true);

        LogHelper.debug("CHAT      >> Connected to the chat server: " + Constants.API_CHAT_SERVER_ADDRESS);
    } catch (UnknownHostException e) {
        LogHelper.error("Unable to open chat connection", e);
        throw new ChatException("Unable to open chat connection", e);
    } catch (IOException e) {
        LogHelper.error("Unable to open chat connection", e);
        throw new ChatException("Unable to open chat connection", e);
    }
}

2 个答案:

答案 0 :(得分:1)

通过基于套接字的连接发送/接收的数据量是协议依赖的,并且TCP / IP堆栈不知道,但仅限于应用层。

使用的协议是开发人员依赖... ;-)所以提出你的问题:

  

如果我只读取我应该阅读的字节,那是否意味着我要么:

     
      
  • 事先知道服务器响应的长度吗?
  •   

是的,这是一种可能性。

  
      
  • 或让服务器发送代码通知它已完成发送响应?
  •   

同样是的,因为这是另一种可能性。常见标记为\n\r\nNUL / '\0'字符也可能有意义。

第三个选项是为每个数据块添加一个常量字节数,用于描述要传输的字节数。

答案 1 :(得分:1)

而不是处理字节,也许它更简单地处理ad-hoc类的实例,例如 - 消息类:

服务器:

// Streams
protected ObjectInputStream fromBuffer = null;
protected ObjectOutputStream toBuffer = null;

// Listening for a new connection
ServerSocket serverConn = new ServerSocket(TCP_PORT);
socket = serverConn.accept();
toBuffer = new ObjectOutputStream(socket.getOutputStream());
fromBuffer = new ObjectInputStream(socket.getInputStream());

// Receiving a new Message object
Message data = (Message)fromBuffer.readObject();

客户端然后只需发送一条消息:

// Sending a message
Message data = new Message("Hello");
toBuffer.writeObject(data);

消息可以根据需要复杂化,只要其成员实现 Serializable 接口。