Задержка Unity в отправке текущего значения при использовании сокетов
Клиент.cs в 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();
}
}
}
Сервер.cs в единстве
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: Ок, я обновил оба скрипта. Сервер и клиент соединяются без проблем вообще. Я могу видеть обновленные значения, когда проверяю показания на сервере. Моя единственная проблема сейчас-это задержка. Метод клиента запускается каждый раз, когда изменяется значение частоты сердечных сокращений. Когда я устанавливаю valu на метку, она показывает мне изменение почти в реальном времени. Но на стороне сервера, значение требуется 6 секунд, чтобы догнать новое значение (которое к тому времени уже отправило другое новое значение). Надеюсь, кто-нибудь объяснит почему.
Обновление 4: неважно! Я понял, в чем проблема. Это было связано с тем, что TcpClient инициализировался каждый раз при запуске метода. Это создало задержку. Я переместил его в Forms_Load и прокомментировал s. Close () и клиент.Закрывать(). Задержка стала намного меньше, всего около секунды, что меня вполне устраивает. Но сейчас мне просто нужно выяснить, когда и как должен ли я закрыть поток и TcpClient. Я пробую окружающую среду.HasShutdownStarted, чтобы проверить, когда приложение закроется, чтобы закрыть клиента и поток тоже, но он не работает.
Обновление 5: хорошо, исправлена последняя проблема с помощью https://msdn.microsoft.com/en-us/library/system.windows.forms.application.applicationexit(v=vs. 110).aspxВсе готово!
2 ответа:
Я думаю, дело в том, что вы поместили все серверные материалы в обновление. А это значит, что его будут вызывать каждый кадр. А это очень много.
Вероятно, вам следует поместить все это в отдельный метод и вызвать его из клиента.
Вы запускаете и выключаете потоки на каждом кадре. Переместите ваши s, sr и sw инициализируют метод Start и используют OnApplicationQuit для закрытия.
void OnApplicationQuit() { s.Close(); soc.Close(); }
При этомUnity все равно будет висеть , поскольку ReadLine не является асинхронным и блокирует выполнение до тех пор, пока сокет не получит данные.
Первые два способа, которые я могу придумать, чтобы обойти это:
- использование потоков
- использование асинхронных обратных вызовов (что я и делаю на своих UDP серверах в Unity 3D). Смотрите этот вопрос: Что такое AsyncCallback?