这是this question的继续,因为它回答了我的原始问题,但并没有解决该错误。

问题:

  • 我该如何解决卡在此行上的代码 inStream.readline()

  • 我的意图:
  • 这是一个线程,该线程将循环检查是否存在outMessage,如果存在,则将发送消息。
  • 接下来,它将检查流内是否有任何内容,如果存在,则将其发送到我的主 Activity 中的处理程序中。
  • 最后,它将休眠1秒钟,然后再次检查。
  • 这应该允许我多次读取/写入,而无需关闭和打开套接字。

  • 问题:
  • 它的读写性能更好,但仍然无法正常工作

  • 现在正在发生什么:
  • 如果outMessage用一个值初始化,则在与服务器连接时,套接字:
  • 写入并刷新值(服务器接收并响应)
  • 更新outMessage的值(根据我的硬编码方式,将其更新为null或“x”)
  • 读取并显示服务器
  • 的响应消息
  • 重新输入下一个循环
  • 如果我将outMessage设置为null,它将跳过if语句正确然后挂起的情况;否则,如果我将outMessage设置为字符串(让我们说“x”),它将遍历整个if语句,然后挂起。
  • 卡在上的代码是 inStream.readline()调用中的任何一个(我目前有一个注释掉了)。

  • 附加信息:
    -连接后,我可以在“发送”框中键入内容,提交(更新outMessage值),然后断开连接。重新连接后,它将读取该值并再次执行序列,直到它卡在同一行上。

    自引用问题以来的变化:
    -将outMessage和connectionStatus都设置为“volatile”
    -在必要的地方添加了行尾定界符。

    代码:
            public void run() {
                while (connectionStatus != TCP_SOCKET_STATUS_CONNECTED) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                while (connectionStatus == TCP_SOCKET_STATUS_CONNECTED) {
                    try {
                        if (outMessage != null){
                            OutStream.writeBytes(outMessage + "\n");
                            OutStream.flush();
                            sendMessageToAllUI(0, MAINACTIVITY_SET_TEXT_STATE, "appendText" , "OUT TO SERVER: " + outMessage);
                            outMessage = "x";
                        }
                        Thread.sleep(100);
     //             if (InStream.readLine().length() > 0) {
                            String modifiedSentence = InStream.readLine();
                            sendMessageToAllUI(0, MAINACTIVITY_SET_TEXT_STATE, "appendText" , "IN FROM SERVER: " + modifiedSentence);
    //                  }
                        Thread.sleep(1000);
                    } catch (IOException e) {
                        connectionLost();
                        break;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    

    构成套接字的线程:
    public void run() {
            setName("AttemptConnectionThread");
            connectionStatus = TCP_SOCKET_STATUS_CONNECTING;
            try {
                SocketAddress sockaddr = new InetSocketAddress(serverIP, port);
                tempSocketClient = new Socket(); // Create an unbound socket
    
                // This method will block no more than timeoutMs. If the timeout occurs, SocketTimeoutException is thrown.
                tempSocketClient.connect(sockaddr, timeoutMs);
                OutStream = new DataOutputStream(tempSocketClient.getOutputStream());
                InStream = new BufferedReader(new InputStreamReader(tempSocketClient.getInputStream()));
                socketClient = tempSocketClient;
                socketClient.setTcpNoDelay(true);
                connected();
            } catch (UnknownHostException e) {
                connectionFailed();
            } catch (SocketTimeoutException e) {
                connectionFailed();
            } catch (IOException e) {
                // Close the socket
                try {
                    tempSocketClient.close();
                } catch (IOException e2) {
                }
                connectionFailed();
                return;
            }
        }
    

    服务器:
    public static void main(String[] args) throws IOException {
        String clientSentence;
        String capitalizedSentence;
        try {
            ServerSocket welcomeSocket = new ServerSocket(8888);
            SERVERIP = getLocalIpAddress();
            System.out.println("Connected and waiting for client input!\n Listening on IP: " + SERVERIP +"\n\n");
            Socket connectionSocket = welcomeSocket.accept();
            BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
            DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
            while(true)
            {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                clientSentence = inFromClient.readLine();
                System.out.println("clientSentance == " + clientSentence);
                String ip = connectionSocket.getInetAddress().toString().substring(1);
                if(clientSentence != null)
                {
                    System.out.println("In from client ("+ip+")("+ System.currentTimeMillis() +"): "+clientSentence);
                    capitalizedSentence = clientSentence.toUpperCase() + '\n';
                    outToClient.writeBytes(capitalizedSentence + '\n');
                    System.out.println("Out to client ("+ip+"): "+capitalizedSentence);
                }
            }
        } catch (IOException e) {
            //if server is already running, it will not open new port but instead re-print the open ports information
             SERVERIP = getLocalIpAddress();
             System.out.println("Connected and waiting for client input!\n");
             System.out.println("Listening on IP: " + SERVERIP +"\n\n");
    
        }
    }
    

    提前致谢!

    编辑:
  • 在更新
  • 之后添加了服务器代码
  • 我尝试弄乱为套接字设置SoTimout,但是将其撤回了
  • 最佳答案

    您需要检查是否有可用数据:

    if (InStream.available > 0) {
       String modifiedSentence = InStream.readLine();
       sendMessageToAllUI(0, MAINACTIVITY_SET_TEXT_STATE, "appendText" , "IN FROM SERVER: " + modifiedSentence);
    }
    

    但是,老实说,即使那样也不是很理想,因为您无法保证会收到首发信息。如果服务器发送了几个字节,但是从不发送行尾,那么您将永远被阻塞。生产套接字代码不应依赖readLine,而应读入缓冲区并检查该缓冲区的行尾(或协议(protocol)所需的任何条件)。

    阅读不够仔细,我以为InStreamInputStream实例。 InputStream具有availableInputStreamReader具有ready(又称为InputStream.available。只要您对这两个参数都保持引用,就可以查看是否可以读取数据。

    10-08 03:11