簡體   English   中英

從Socket讀取的Android在第二個讀取循環中掛起

[英]Android reading from Socket hangs on second read loop

我必須在我的應用程序中實現聊天。 使用套接字連接到服務器。 我應該注冊到該服務器,服務器將通過回復知道。

我已經在一個方法中實現了這個,我使用BufferedWriter發送命令,然后從輸入流開始讀取,直到它告訴我沒有更多的數據。

我正確閱讀了服務器回復。 但是,我從來沒有從第二個in.read調用中得到負值,因此我的方法在while循環中被阻塞(在我調用的條件語句中)。

如何用套接字完成? 我通常使用文件或其他輸入流沒有問題。

如果我只讀取我應該閱讀的字節,這是否意味着我要么:

  • 事先知道服務器響應的長度?
  • 或者讓服務器發送代碼通知它已完成發送響應?

目前我正在做以下事情:

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

通過基於套接字的連接發送/接收的數據量是協議依賴的,並且TCP / IP堆棧不知道,但僅限於應用層。

使用的協議是開發人員dependend ... ;-)所以提出你的問題:

如果我只讀取我應該閱讀的字節,這是否意味着我要么:

  • 事先知道服務器響應的長度?

是的,這是一種可能性。

  • 或者讓服務器發送代碼通知它已完成發送響應?

也是,因為這是另一種可能性。 常用標記是\\n\\r\\n NUL / '\\0'字符也可能有意義。

第三種選擇是為每個數據塊添加一個恆定數量的字節,用於描述要來的字節數。

也許它更簡單地處理ad-hoc類的實例,比如 - 例如 - Message類:而不是處理字節。

服務器:

// 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接口, 消息就可以根據需要復雜

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM