来自流的KotlinBufferedReader正在阻塞

vbopmzt1  于 2023-02-05  发布在  Kotlin
关注(0)|答案(1)|浏览(151)

我正在创建一个Android应用程序与Visual Studio时钟,我试图使我的C++服务器之间的通信(工作完美)和我的Android应用程序。我的Android套接字(客户端)正确连接到我的服务器,我可以发送消息到服务器,但当服务器发送消息的readText块infinitly。这里的代码为当前片段:

package com.example.androidapp

import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.androidapp.databinding.FragmentServerMainBinding
import androidx.navigation.fragment.findNavController
import java.io.Reader

import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.*

class ServerMainFragment : Fragment() {
    //private var _binding: FragmentFirstBinding? = null
    private var _binding: FragmentServerMainBinding? = null
    // This property is only valid between onCreateView and
    // onDestroyView.
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentServerMainBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        singleton_ServerInfos.end=false
        binding.bBisconnect.setOnClickListener {
            singleton_ServerInfos.end=true;
            Log.d("ServerMainFragment", "closing socket")
            singleton_ServerInfos.clientSocket?.close();
            (context as Activity).runOnUiThread(java.lang.Runnable {
                Log.d("ServerMain: ", "disconnecting")
                findNavController().navigate(R.id.FirstFragment)
            })
        }

        binding.sendmsg.setOnClickListener {
            Thread(Runnable {
                try {
                    Log.d(
                        "ServerMainFragment",
                        "sendmsg" + singleton_ServerInfos.clientSocket.isConnected
                    )
                    singleton_ServerInfos.clientSocket?.outputStream.write("Hello from the client!".toByteArray())
                } catch (excep: java.net.SocketException) {
                    Log.d("SocketException", "catched error")
                } catch (e: Exception) {
                    Log.d("Exception", e.toString() + "---" + e.message)
                }
            }).start()
        }
        listenForServerMessage()
        Log.d("FirstFragment", "onViewCreated")
    }

    fun listenForServerMessage() {
        //var reader = Scanner(singleton_ServerInfos.clientSocket.getInputStream())
        Log.d("ServerMain ", "listenForServerMessage")
        Thread(Runnable {
            try {
                Log.d("ServerMain ","letsgo:"+singleton_ServerInfos.end);

                var bufReader = BufferedReader(InputStreamReader (singleton_ServerInfos.clientSocket.getInputStream()))
                while (singleton_ServerInfos.end!=true) {
                    Log.d("ServerMain ", "while")
                    var nbr = singleton_ServerInfos.clientSocket.getInputStream().available()
                    if (nbr != 0) {
                        Log.d("ServerMain read: ", "in:"+nbr+"-"+bufReader.ready());
                        if (bufReader.ready())
                            Log.d("ServerMain read: ",  "NOOWOWW:"+bufReader.readText());
                    }
                }
            }
            catch (e: Exception) {
                Log.d("ServerMain: ", "exception closing.")
            }
        }).start()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

套接字连接到上一个片段。在阅读函数listenForServerMessage中,我检查套接字是否准备好,我检查接收的字节数(非零),如果缓冲区也准备好,两者都很好,但当执行readText时,我得到了一个无限循环。我的日志如下所示:

D/ServerMain: letsgo:false
D/ServerMain: while
I/chatty: uid=10122(com.example.androidapp) Thread-3 identical 73 lines
D/ServerMain: while
D/FirstFragment: onDestroyView
D/ServerMain: while
...same while log until i send a message from the server...
I/chatty: uid=10122(com.example.androidapp) Thread-3 identical 1686 lines
D/ServerMain: while
D/ServerMain read:: in:8-true

我尝试了很多东西,但无法找到解决方案,我知道我的套接字正确接收消息,因为如果我关闭C++服务器,Android套接字finaly读取消息。(我计划在未来通过套接字发送图像缓冲区)

falq053o

falq053o1#

好的,我找到了解决方案,唯一能让我进行非阻塞读取的方法是在读取函数中使用CharArray,其他函数都以无限循环结束(即使是没有参数的read())。下面是现在工作的代码:

fun listenForServerMessage() {
        //var reader = Scanner(singleton_ServerInfos.clientSocket.getInputStream())
        Log.d("ServerMain ", "listenForServerMessage")
        Thread(Runnable {
            try {
                Log.d("ServerMain ","letsgo:"+singleton_ServerInfos.end);

                var bufReader = BufferedReader(InputStreamReader (singleton_ServerInfos.clientSocket.getInputStream()))
                while (singleton_ServerInfos.end!=true) {
                    Log.d("ServerMain ", "while")
                    var nbr = singleton_ServerInfos.clientSocket.getInputStream().available()
                    if (nbr != 0) {
                        Log.d("ServerMain read: ", "in:"+nbr+"-"+bufReader.ready());
                        var mchar : CharArray = CharArray(nbr)
                        if (bufReader.ready()) {
                            bufReader.read(mchar)
                            Log.d("ServerMain read: ", "!!!:" +mchar.concatToString());
                        }
                        else
                            Log.d("ServerMain ", "fail")
                    }
                }
            }
            catch (e: Exception) {
                Log.d("ServerMain: ", "exception closing.")
            }
        }).start()
    }

我现在将实现我想如何使用我的服务器的逻辑,如果我发现这个问题的原因,我将编辑我的答案。

相关问题