Unity delay in sending the current value when usin

2020-03-30 02:12发布

问题:

The client.cs in Visual Studio.

private void SendToServer(string HeartRate)
    {
        SetHRTest(HeartRate);
        try
        {
            s = client.GetStream();
            StreamReader sr = new StreamReader(s);
            StreamWriter sw = new StreamWriter(s);
            sw.AutoFlush = true;
            sw.WriteLine(HeartRate);
        }
        finally
        {
            if(Environment.HasShutdownStarted)
            {
                s.Close();
                client.Close();
            }
        }
    }

The server.cs in Unity

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Threading;

public class Server {

public static TcpListener listener;
public static Socket soc;
public static NetworkStream s;
static public string CurrentHeartRate = "";
// Use this for initialization
public void StartService () {
    listener = new TcpListener (15579);
    listener.Start ();
    for(int i = 0;i < 1;i++){
         Thread t = new Thread(new ThreadStart(Service));
        t.Start();
        Debug.Log("3");
    }

}
void Service () {
    while (true) 
    {
        soc = listener.AcceptSocket ();
        s = new NetworkStream (soc);
        StreamReader sr = new StreamReader (s);
        StreamWriter sw = new StreamWriter (s);
        sw.AutoFlush = true;
        while(true)
        {
            string heartrate = sr.ReadLine ();
            if(heartrate != null)
            {
                CurrentHeartRate = heartrate;
                Debug.Log(heartrate);
            }
            else if (heartrate == null)
            {
                break;
            }
        }
        s.Close();
    }
}

void OnApplicationQuit()
{
    Debug.Log ("END");
    listener.Stop ();
    s.Close();
    soc.Close();
}

}

UPDATE 3: Ok, I have updated both scripts. The server and client connects with no problems at all. I am able to see updated values when I check the readings in the server. My only issue right now is, delay. The client method is initiated every time the heart rate value is changed. When I set the valu to a label, it shows me a near real time change. But at the server side, the value takes 6 seconds to catchup with the new value (which by then has already sent another new value). Hope someone can clarify why.

UPDATE 4: Nevermind! I figured out the problem. It was due the TcpClient being initialized every time the method was run. This created the delay. I moved it up to the Forms_Load and commented out the s.Close() and client.Close(). The delay became much less, just near a second which is fine by me. Now though, I just need to find out when and how should I close the stream and TcpClient. I am trying the Environment.HasShutdownStarted to check when the application will close to shut the client and stream too but it is not working.

UPDATE 5: Alright, fixed the last issue by using the https://msdn.microsoft.com/en-us/library/system.windows.forms.application.applicationexit(v=vs.110).aspx! All Done!

回答1:

I think it's the fact that you put all the server stuff in the Update. Which means it'll get called every frame. Which is a lot.

You should probably put all this in a separate method and call that from the client.



回答2:

You are starting and shutting down the streams at every frame. Move your s, sr and sw initializations to the Start method and use OnApplicationQuit for closing.

void OnApplicationQuit()
{
   s.Close();
   soc.Close();
}

Doing so Unity will still hang as ReadLine is not asynchronous and will lock the execution until your socket receives data.

First two ways I can think of to go around this are:

  • using threads
  • using async callbacks (which I do in my UDP servers in Unity 3D). See this question: What is AsyncCallback?