我正在嘗試學習游戲網路編程,所以我使用 Unity 啟動了一個非常簡單的異步 udp 套接字系統,但是當我添加 JSON 序列化時,事情變得有點奇怪。
我可以連接到服務器并使用該SendPacket(string msg)方法發送資料包,它會在服務器端正常接收。只要 msg 變數的大小相同或更大,它就可以正常作業。因此,如果我發送一個字串“Hello”,然后一個“Hello World”將正常作業,并且能夠以其他尺寸列印它。但是,如果我現在要發送另一個帶有字串“Hi”的資料包,則不會發生任何事情,并且該套接字上將不再有連接,也不會發送新資料包。
我已經檢查過了,我正在通過網路接收資料包,它不是空的,它有資訊但是當它到達代碼時它似乎停止了:
Packet p = e.Buffer.FromJsonBinary<Packet>();
這是我服務器端的 OnConnect 功能。在該功能之后似乎我的服務器停止偵聽不接受新連接并且不會接收其他資料包,我懷疑它以某種方式停止了我的異步行程。
對于 Json 序列化,我使用 Unity 的 JsonUtility。
任何想法發生了什么?
服務器類
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");
}
}
}
客戶端類
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 序列化
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));
}
包
[Serializable]
public struct Packet
{
public string _protocolID;
public string _msg;
public Packet(string protocolID, string msg)
{
_protocolID = protocolID;
_msg = msg;
}
}
編輯:我發現它由于 Json Utility 而崩潰
System.ArgumentException: JSON parse error: The document root must not follow by other values.
發送前的 Json 字串(上),服務器收到的 Json 字串(下)
似乎在服務器上緩沖區沒有被清除,所以它仍然有資訊。
uj5u.com熱心網友回復:
好的,看來問題是由于 SocketAsyncEventArgs 的作業原理。由于我遞回呼叫并傳遞相同的事件,它永遠不會清除它的緩沖區。
if (!_socket.ReceiveAsync(e))
{
OnConnect(null, e);
}
我發現了兩種解決方案,一種是傳遞一個新的 SocketAsyncEventArgs ,它將有一個清晰的緩沖區。但我相信一個更好的主意是創建一個池來處理和重用一組預定義的 SocketAsyncEventArgs,而不是不斷地創建新的。
我發現的另一個解決方案是簡單地設定一個新緩沖區作為清除最后一個緩沖區的方法。
byte[] buffer = t.ToJsonBinary();
_event.SetBuffer(buffer, 0, buffer.Length);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/416071.html
標籤:
上一篇:旋轉游戲物件后將運動凍結到一邊
下一篇:每波增加敵人的生命值
