I'm creating an android app with visual studio on clocking, and I'm trying to make the communication between my C++ server (working perfectly) and my android app. My android socket (client) connect correctly to my serv, i can send message to the server, but when the server is sending message the readText block indefinitly. here the code for the current fragment :
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
}
}
The socket is connected on the previous fragment. In the reading function listenForServerMessage , i check if the socket is ready, i check the number of bytes received (non zero) and if the buffer is also ready, both are good but when executing readText i get an infinite loop. my log look like this :
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
I tried many thing but can't figure a solution, and i know my socket correctly receive the message because if i close the C++ server, the android socket finaly read the message. (i'm planning to send image buffer through the socket in the future)
clientSocket.getInputStream()directly if you already wrapped it in a buffered reader. What if buffered reader read the message already and stored it in its internal buffer?available()for the original stream will return0while we have data to read from the buffered reader.