Android TCP 应用程序挂在 inStream.readline() 上

2023-11-29

这是一个延续这个问题因为它回答了我原来的问题,但它没有解决错误。

问题:

  • 如何修复挂在这一行的代码inStream.readline()

我的意图:

  1. 这是在一个线程中,该线程将循环检查是否有 outMessage,如果有,它将发送消息。
  2. 接下来,它将检查流中是否有任何内容,如果有,它会将其发送到我的主要活动中的处理程序。
  3. 最后,它会休眠 1 秒,然后再次检查。
  4. 这应该允许我多次读/写,而无需关闭和打开套接字。

Problem:

  • 阅读和写作更好了,但仍然无法正常工作

现在发生了什么:

  • If outMessage is initialized with a value, upon connection with the server, the socket:
    1. 写入并刷新值(服务器接收并响应)
    2. 更新 outMessage 的值(为 null 或“x”,具体取决于我如何对其进行硬编码)
    3. 读取并显示来自服务器的响应消息
    4. 重新进入下一个循环
    5. IF i set outMessage to null, it skips over that if statements correctly then hangs; otherwise, if i set outMessage to a string (lets say "x"), it goes through the whole if statement, then hangs.
      • 代码它hangs on是其中之一inStream.readline()调用(我目前已经注释掉了一个)。

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

自引用问题以来的变化: - 使 outMessage 和 connectionStatus 均为“易失性” - 在必要的地方添加了行尾分隔符。

Code:

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

Server:

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

    }
}

提前致谢!

Edits:

  • 更新后添加了服务器代码
  • 我尝试为套接字设置 SoTimout,但又把它取消了

您的服务器经过专门设计,可以从客户端接收一行,并返回一行。看代码:

    while (true) {
        Socket connectionSocket = welcomeSocket.accept();
        BufferedReader inFromClient = new BufferedReader(
                new InputStreamReader(connectionSocket.getInputStream()));
        DataOutputStream outToClient = new DataOutputStream(
                connectionSocket.getOutputStream());

        clientSentence = inFromClient.readLine();
        String ip = connectionSocket.getInetAddress().toString()
                .substring(1);
        System.out.println("In from client (" + ip + "): "
                + clientSentence);
        if (clientSentence != null) {
            capitalizedSentence = clientSentence.toUpperCase() + '\n';
            System.out.println("Out to client (" + ip + "): "
                    + capitalizedSentence);
            outToClient.writeBytes(capitalizedSentence + "\n");
        }

请注意,在循环内部,它接受一个新连接,读取一行,然后写入一行。它不会关闭连接。它并没有完全结束谈话。它只是停止阅读。

使用该服务器的客户端必须进行连接、发送一行、读回一行,然后客户端必须关闭连接。你的客户不会这样做。为什么?因为你不知道那是你必须做的。为什么?因为你没有设计……没有计划。

这就是你的具体问题。但是请让我敦促你采取huge退后一步,彻底改变你的方法。在编写一行代码之前,请实际设计并指定字节级别的协议。协议应该说明发送什么数据、如何分隔消息、谁何时发送、谁关闭连接等等。

否则,无法调试您的代码。看看上面的服务器代码,是否正确?好吧,谁知道呢。因为不清楚它应该做什么。当您编写客户端时,您假设服务器以一种方式运行。这个假设有效吗?服务器坏了吗?谁知道呢,因为没有规范服务器应该做什么。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android TCP 应用程序挂在 inStream.readline() 上 的相关文章

  • 当用户快速滚动时,如何延迟列表适配器中视图的加载

    我的列表视图中有从互联网下载的图像 我想在 getView 中添加一些内容 以便在用户快速滑动 滚动时它不会下载图像 我怎样才能开始这样做呢 您可以按照以下步骤延迟 ListView 中视图的加载 首先 你应该让你的ListView对象和Y
  • Android Studio Profiler 中显示“无可调试进程”

    当我尝试在 Android Studio 中使用探查器时 我能够看到已连接的设备 但在探查器中收到 无可调试进程 有人可以帮助我为什么我收到 不可调试的进程 吗 您可以尝试以下任意 全部操作 使缓存失效并重新启动Android Studio
  • ZMQ:XPUB 套接字上没有多个订阅者的订阅消息(最后值缓存模式)

    我实现了 ZMQ 的最后值缓存 LVC 示例 http zguide zeromq org php chapter5 Last Value Caching http zguide zeromq org php chapter5 Last V
  • SQLite 中的 where 子句在 android 中不起作用:(

    当尝试在 SQLite 中查询某些数据时 我遇到了一个恼人的错误 这是我的代码 Cursor cursor db query TABLE IMAGES new String id name compareToThis null null n
  • 在 docker 容器内创建 android 模拟器时出现“sh: 1: file: not found”

    我正在尝试在 docker 容器内创建一个 android 模拟器 但遇到了一些问题 SDK 更新和 AVD 创建成功 我尝试创建模拟器 出现以下错误 emulator avd test 22 no skin no audio no win
  • 字符串生成器最大长度

    我想知道字符串生成器 或字符串缓冲区 的最大容量是多少 我的 Android 应用程序中有一个静态变量 它应该保存日志字符串 它最多可以容纳 130 行和大约 10000 个字符 我如果我附加更多内容 但它只是不显示 没有错误 没有例外 所
  • 如何调试使用maven构建的android应用程序

    我目前正在尝试从 Eclipse 调试我的设备上的 Android 应用程序 设备已添加 我可以在控制台和 Eclipse 中看到它 控制台 Windows adb devices List of devices attached 0019
  • Eddystone Beacon 中广播的 MAC ID 会改变吗?

    我将描述我的设置 我制作了一个模拟 Eddystone 信标的 Android 应用程序 我能够使用 PlayStore 中的 Beacon Toy 应用程序检测手机上的 Eddystone 信标 但问题是 自上次检查以来 显示的 MAC
  • 旧 Android SDK 版本上的 java.lang.NoClassDefFoundError

    我在 Google Play 上发布了我的应用程序的一个版本 今天早上醒来时发现了一些不满意的客户 该应用程序的最新版本集成了对蓝牙低功耗 BTLE 心率监测器的支持 该应用程序在 Android 4 3 和 4 4 上运行良好 但在 4
  • 如何在android上模拟PC的Esc键

    我正在写一个可以在android上玩flash的应用程序 但是我无法模拟ESC键 因为很多flash游戏需要ESC键才能返回主菜单 没有这个键我制作的应用程序将毫无用处 谁能告诉我如何模拟这个 我可以只发送一个密钥代码吗 但我也不知道键码
  • Kotlin + Room:java.lang.IllegalArgumentException:void 无法转换为元素

    我试图在我的 Java Kotlin 项目中添加 Room 但是当我尝试编译该项目时 它失败了 app kaptDebugKotlin出现以下错误 e java lang IllegalStateException failed to an
  • 使用 Backstack 时 TabLayout ViewPager 未加载 [重复]

    这个问题在这里已经有答案了 我在一个片段中使用 TabLayout 和 viewPager 在选项卡下方的两个片段之间切换 当我单击下部片段之一内的 FAB 时 我会加载一个新片段 用于输入 但是 当我按 后退 按钮时 TabLayout
  • 更改适配器数据时,RecyclerView 滚动到顶部位置

    我正在对某个帖子进行喜欢和不喜欢RecyclerView 我在更改视图后调用api 但问题是RecyclerView当我通知它更新时 总是滚动到顶部 这是我的适配器代码 likeAnim setOnLikeListener object O
  • Android SSH 示例代码

    我想创建一个 android 活动 用于与远程设备 通过 Wifi 建立 SSH 会话并在远程设备上执行一些 Linux 命令 任何人都可以获得一个快速 简短的示例 用于使用以下命令进行连接 身份验证和发送远程命令Trilead https
  • 如何在flutter上关注android tv应用程序中的列表视图项目

    我想在 flutter 中构建一个 android 电视应用程序 几乎所有事情都已完成 但一个问题是我无法集中注意力 例如一些弹出效果或边框更改任何告诉用户您现在正在使用此项目的内容 我们在列表视图中迭代的项目 我想要在应用程序中看到的图像
  • 协程中未捕获异常

    我似乎无法在协程中完成错误处理 我读了很多文章并且异常处理文档 https kotlinlang org docs reference coroutines exception handling html exception propaga
  • 具有通用类的自定义 Android 适配器

    我正在尝试在 Android 中创建一个通用适配器 所以我不能一遍又一遍地编写它 问题是 它正在工作 但它的回收效果不是很好 它显示了我想要的内容 但是当我滚动时 它的顺序不同 public class CustomListViewAdap
  • Android:适合SystemWindows和换行符干扰bottomSheets

    我发现如果父布局包含android fitsSystemWindows true 当发生与视图相关的操作时 它会干扰我的 BottomSheets 定位 具体来说 我遇到的是 文本视图中的换行符将触发底页偏移系统 通知栏的高度 换行符 fi
  • 在 Android 中将列表传递给另一个 Activity

    我已经创建了一个列表 并希望将该列表传递给另一个活动 但当我创建意图时 我在 putExtra 语句上收到错误 只是想知道是否有任何简单的方法来传递字符串列表而不是单个字符串 Thanks private List
  • Android:如何获取所有可用意图过滤器的列表?

    我搜索了 Android 文档 但由于某些疯狂的原因 我无法找到所有可用意图过滤器的列表 我正在寻找一个意图过滤器 它可以执行诸如通过广播接收器通知我特定活动 例如浏览器或电子邮件 已启动或位于前台之类的操作 有人能帮我吗 PackageE

随机推荐