1

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)

7
  • Do you flush at the server side after writing? Commented Feb 3, 2023 at 22:44
  • no i dont, it's a c++ server so i don't have the "flush" functionnality, but it's working well with my C++ client, but i will check what does the flush function, maybe it's a character to send :) Commented Feb 3, 2023 at 22:49
  • Also, I think you shouldn't interact with 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 return 0 while we have data to read from the buffered reader. Commented Feb 3, 2023 at 22:51
  • I found the flush function, but there seem to be no character send :( android flush geek flush, i'm currently trying to send random non visible ascii character from my c++ server Commented Feb 3, 2023 at 23:08
  • I tried every character to add (from 0 to 255) at the end of my message, none worked Commented Feb 3, 2023 at 23:23

1 Answer 1

1

Ok i found the solution, the only for me to have a non-blocking read is to use a CharArray in the read function, every other function end-up in a infinite loop (even read() without argument) Here the code that work now:

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

I will now implement the logic of how i wanted to use my server, if i found a cause of this problem, i will edit my answer.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.