Home > OS >  NetworkStream receives an empty string data in Unity
NetworkStream receives an empty string data in Unity

Time:10-07

I run client code on Unity and server code on a console application. The problem is that when the server sent a 'welcome' message to the client, the client receives an empty message. But weirdly when I run the code on Unity in debug mode it works well. Does anyone know why this happens?

Here is the client code

    public class Test: MonoBehaviour
    {
        TcpClient client;
        NetworkStream networkStream;        
        string stringData;
        byte[] data;

        private void Start()
        {
            StartClient();
        }

        private void OnApplicationQuit()
        {
            if (networkStream != null)
            {
                if (networkStream.CanRead && networkStream.CanWrite) networkStream.Close();
            }

            if (client.Connected) client.Close();
        }

        private void StartClient()
        {
            client = new TcpClient();
            client.BeginConnect("127.0.0.1", 7777, DefaultConnectCallback, client);            
        }

        private void DefaultConnectCallback(IAsyncResult ar)
        {
            TcpClient client = (TcpClient)ar.AsyncState;

            networkStream = client.GetStream();
            data = new byte[1024];
            networkStream.BeginRead(data, 0, data.Length, DefaultReadCallback, networkStream);
            stringData = System.Text.Encoding.ASCII.GetString(data).Trim('\0');
            Log.LogMessage("Recieved a message");
            Log.LogMessage(stringData);
            Log.LogMessage($"{stringData.Length}");            
        }

        private void DefaultReadCallback(IAsyncResult ar)
        {
            NetworkStream networkStream = (NetworkStream)ar.AsyncState;
            networkStream.EndRead(ar);
        }
    }

Here is the server code

class Program
    {        
        public static Action OnExit;

        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.ProcessExit  = new EventHandler(OnProcessExit);

            TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 7);
            listener.Start();   
            Log.LogMessage("Server Started");

            OnExit  = () => 
            {
                foreach(var client in clients)
                {
                    client?.GetStream()?.Close();
                }

                listener.Stop();
            };

            listener.BeginAcceptTcpClient(DefaultAcceptCallback, listener);            

            Console.ReadKey();
        }                

        static void OnProcessExit(object sender, EventArgs e)
        {                
            if (OnExit != null) OnExit();    
        }

        static TcpClient[] clients = new TcpClient[10];
        static int connection = 0;

        static void DefaultAcceptCallback(IAsyncResult ar)        
        {
            TcpListener listener = (TcpListener)ar.AsyncState;
            TcpClient newClient = listener.EndAcceptTcpClient(ar);
            NetworkStream networkStream = newClient.GetStream();
            byte[] welcome;

            Log.LogMessage($"Connect request No.{connection} accepted");            
            clients[connection] = newClient;
            welcome = Encoding.ASCII.GetBytes("Welcome!");
            networkStream.BeginWrite(welcome, 0, welcome.Length, DefaultReadCallback, networkStream);
            Log.LogMessage($"Welcome message sent");
            connection  ;
            listener.BeginAcceptTcpClient(DefaultAcceptCallback, listener);
        }

        static void DefaultWriteCallback(IAsyncResult ar)
        {
            NetworkStream networkStream = (NetworkStream)ar.AsyncState;
            networkStream.EndWrite(ar);
        }
    }    

CodePudding user response:

networkStream.BeginRead(data, 0, data.Length, DefaultReadCallback, networkStream);
    

is a non-blocking call and you immediately continue with your code.

You have to wait until actually something has been received!

    private void DefaultConnectCallback(IAsyncResult ar)
    {
        TcpClient client = (TcpClient)ar.AsyncState;

        networkStream = client.GetStream();
        data = new byte[1024];
        networkStream.BeginRead(data, 0, data.Length, DefaultReadCallback, networkStream);
    }

    private void DefaultReadCallback(IAsyncResult ar)
    {
        NetworkStream networkStream = (NetworkStream)ar.AsyncState;
        networkStream.EndRead(ar);

        stringData = System.Text.Encoding.ASCII.GetString(data).Trim('\0');
        Log.LogMessage("Recieved a message");
        Log.LogMessage(stringData);
        Log.LogMessage($"{stringData.Length}");            
    }

See NetworkStream.BeginRead and also the example of NetworkStream.EndRead

  • Related