Я изучаю простые сети с использованием Unity и Sockets, и у меня возникают проблемы с синхронизацией данных между клиентом и сервером. Я знаю, что есть и другие варианты использования Unity Networking, но прежде чем двигаться дальше, я хочу лучше понять, как улучшить свой код с помощью системных библиотек.
В этом примере я просто пытаюсь передать свою позицию мыши через многоадресный сокет UDP. Я кодирую строку в массив байтов и отправляю этот массив один раз за кадр. Я знаю, что отправка этих значений в виде строки неоптимальна, но, если только это не является узким местом, я предполагаю, что можно вернуться, чтобы оптимизировать это позже.
Im, мой сервер настройки отправляет значения со скоростью 60 кадров в секунду, и клиент читает с той же скоростью. Проблема, с которой я сталкиваюсь, заключается в том, что когда клиент получает значения, он обычно получает сразу несколько значений. Если я регистрирую значения, которые я получил с -----
между каждым кадром, я обычно получаю вывод следующим образом:
------
------
------
------
------
------
------
119,396
91,396
45,391
18,379
-8,362
-35,342
-59,314
------
------
------
------
------
------
------
Я ожидаю, что несинхронизированные циклы обновления приведут к получению двух значений на кадр, но я не уверен, что может объяснить большее несоответствие.
Вот код сервера:
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class Server : MonoBehaviour
{
Socket _socket;
void OnEnable ()
{
var ip = IPAddress.Parse ("224.5.6.7");
var ipEndPoint = new IPEndPoint(ip, 4567);
_socket = new Socket (AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
_socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption (ip));
_socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2);
_socket.Connect(ipEndPoint);
}
void OnDisable ()
{
if (_socket != null)
{
_socket.Close();
_socket = null;
}
}
public void Send (string message)
{
var byteArray = Encoding.ASCII.GetBytes (message);
_socket.Send (byteArray);
}
}
И клиент:
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class Client : MonoBehaviour
{
Socket _socket;
byte[] _byteBuffer = new byte[16];
public delegate void MessageRecievedEvent (string message);
public MessageRecievedEvent messageWasRecieved = delegate {};
void OnEnable ()
{
var ipEndPoint = new IPEndPoint(IPAddress.Any, 4567);
var ip = IPAddress.Parse("224.5.6.7");
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
_socket.Bind (ipEndPoint);
_socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip,IPAddress.Any));
}
void Update ()
{
while (_socket.Available > 0)
{
for (int i = 0; i < _byteBuffer.Length; i++) _byteBuffer[i] = 0;
_socket.Receive (_byteBuffer);
messageWasRecieved (Encoding.ASCII.GetString (_byteBuffer));
}
}
}
Если бы кто-нибудь мог пролить свет на то, что я могу сделать, чтобы улучшить синхронизацию, это было бы большим подспорьем.
_socket.Receive (_byteBuffer);
— это блокирующий вызов, который вам не нужен в основном потоке. Скорее выполняйте весь процесс получения и преобразования строк в фоновом потоке и отправляйте только полученные сообщения обратно в основной поток. Также отправитель, вероятно, должен просто преобразовать и отправить свой материал в потоке или задаче. По-прежнему не будет реальной гарантии, что вы поймаете ровно один пакет за кадр. В общем, вы все равно можете захотеть обработать только самый последний полученный пакет за кадр и удалить предыдущие. - person derHugo   schedule 10.07.2020UdpClient
и позволить ему обрабатывать базовые сокеты? - person derHugo   schedule 10.07.2020UDPClient
, но также посмотрю, смогу ли я найти возможность отправлять пакеты меньшего размера, чтобы эта версия работала. - person jonathan topf   schedule 10.07.2020