I'm trying to learn Game Networking programming so I started a very simple async udp socket system using Unity, however when I added JSON serialization things got a little bit weird.
I can connect to the server and send packets with the SendPacket(string msg)
method and it will receive it fine on the server side. And it will work fine as long as the size of the msg variable is the same size or bigger. So if I send a string "Hello" and then one "Hello World" will work fine and be able to print it on the other size. However if I was now to send another packet with the string "Hi" nothing would happen and no more connections will work on that socket neither sending new packets.
I have checked and I'm receiving the packet over the network and it's not empty it has the information however it seems to stop when it gets to the code:
Packet p = e.Buffer.FromJsonBinary<Packet>();
Which is on the OnConnect function on my server side.After that function It seems my server stops listening not accepting new connections and no other packets will be receive, I suspect it somehow stops my async process.
For the Json Serialization I'm using JsonUtility from Unity.
Any ideas what is happening?
Server Class
public class Server
{
private static string _protocolID = "hash";
private static ushort _port = 11000;
private Socket _socket;
private SocketAsyncEventArgs _event;
private List<Socket> _connections = new List<Socket>();
public void Start()
{
Listen();
}
private bool Listen()
{
// Create UDP Socket
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// Set the socket into non-blocking mode
_socket.Blocking = false;
try
{
_socket.Bind(new IPEndPoint(IPAddress.Any, _port));
_event = new SocketAsyncEventArgs();
_event.Completed += OnConnect;
byte[] buffer = new byte[1024];
_event.SetBuffer(buffer, 0, 1024);
//_socket.ReceiveAsync(_event);
StartListening(_event);
}
catch (Exception e)
{
Debug.LogException(e);
return false;
}
return true;
}
private void StartListening(SocketAsyncEventArgs e)
{
//e.AcceptSocket = null;
_socket.ReceiveAsync(e);
}
private void OnConnect(object sender, SocketAsyncEventArgs e)
{
if (e.BytesTransferred > 0)
{
if (e.SocketError != SocketError.Success)
Debug.Log("ERROR"); // TODO: Close Socket
Packet p = e.Buffer.FromJsonBinary<Packet>();
if (p._protocolID != _protocolID)
Debug.Log("Protocol Error");
Debug.Log("Connect:" + p._msg);
if (!_socket.ReceiveAsync(e))
{
// Call completed synchonously
StartListening(e);
}
}
else
{
Debug.Log("No data");
}
}
}
Client Class
public class Client
{
private static string _protocolID = "hash";
private ushort _port = 11000;
private string _ip = "127.0.0.1";
private Socket _socket;
private SocketAsyncEventArgs _event;
public bool Connect()
{
// Create UDP Socket
_socket = new Socket(SocketType.Dgram, ProtocolType.Udp);
// Set the socket into non-blocking mode
_socket.Blocking = false;
IPEndPoint ip = new IPEndPoint(IPAddress.Parse(_ip), _port);
_event = new SocketAsyncEventArgs();
//_event.Completed += Callback;
try
{
_socket.Connect(ip);
Debug.Log($"Connection was to {_ip} was sucessfull");
}
catch(Exception e)
{
Debug.LogException(e);
Debug.Log("Couldn't connect Socket");
return false;
}
return true;
}
public void SendPacket<T>(T t)
{
try
{
if (_socket == null)
Debug.Log("Null socket");
// Encode the data string into a byte array.
byte[] buffer = t.ToJsonBinary();
_event.SetBuffer(buffer, 0, buffer.Length);
// Send the data through the socket.
//_socket.SendAsync(_event);
bool willRaiseEvent = _socket.SendAsync(_event);
//if (!willRaiseEvent)
//{
// SendPacket<T>(t);
//}
}
catch (SocketException e)
{a
Debug.LogException(e);
Debug.Log("Couldn't Send Packet");
}
}
public void SendPacket(string msg)
{
Packet packet = new Packet(_protocolID, msg);
SendPacket<Packet>(packet);
}
}
Json Serialization
public static byte[] ToJsonBinary(this object obj)
{
return Encoding.ASCII.GetBytes(JsonUtility.ToJson(obj));
}
public static T FromJsonBinary<T>(this byte[] data)
{
return JsonUtility.FromJson<T>(Encoding.ASCII.GetString(data));
}
Packet
[Serializable]
public struct Packet
{
public string _protocolID;
public string _msg;
public Packet(string protocolID, string msg)
{
_protocolID = protocolID;
_msg = msg;
}
}
Edit: I found out it's crashing due to Json Utility
System.ArgumentException: JSON parse error: The document root must not follow by other values.
Json string before being sent (top), Json string reiceived at the server (bottom)
It seems on the server the buffer isn't being cleared so it still has information in it.