背景
由于要写一个unreal
的mmorpg demo
, 就用python
写了服务器,回头一想,既然unreal
的都已经写了,那就干脆把unity
的也写了~然后在写unity
的网络库udp
的时候,遇到了以下几个问题,于是就记录了以下!
简单的基本代码(问题重现版)
这里只放出C#的代码(前端使用)
public override bool Connect(string url, int port, double timeout=5000){
var MainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
EndPoint RemoteAddress = new IPEndPoint(IPAddress.Parse(url), port);
ThreadStart childref = new ThreadStart(this.ReceiveRun);
receiveThread = new Thread(childref);
receiveThread.Start();
NetPackage package = new NetPackage();
package.Head.Protocol = 1001;
var bytes = package.Encode();
MainSocket.SendTo(bytes, RemoteAddress);
}
private void ReceiveRun()
{
while (IsLoop)
{
byte[] buffer = new byte[1024];
if (Receive(ref buffer))
{
Debug.LogError("receive msg");
}
}
}
public override bool Receive(ref byte[] buffer)
{
base.Receive(ref buffer);
serverEnd = new IPEndPoint(IPAddress.Any, 0);
int len = MainSocket.ReceiveFrom(buffer, ref serverEnd);
return len > 0;
}
问题以及解决思路
上面的代码在运行的时候,直接抛出了以下的异常
SocketException: 提供了一个无效的参数。
System.Net.Sockets.Socket.ReceiveFrom (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint& remoteEP) (at <743b6648c9264b5cabe5d91045f6e132>:0)
System.Net.Sockets.Socket.ReceiveFrom (System.Byte[] buffer, System.Net.EndPoint& remoteEP) (at <743b6648c9264b5cabe5d91045f6e132>:0)
WDFramework.UdpNetDriver.Receive (System.Byte[]& buffer) (at Assets/Framework/Runtime/Network/UdpNetDriver.cs:34)
WDFramework.NetDriver.ReceiveRun () (at Assets/Framework/Runtime/Network/NetDriver.cs:59)
System.Threading.ThreadHelper.ThreadStart_Context (System.Object state) (at <7b935204f5ff4bcab44b3b0ebca330bf>:0)
这里居然说ReceiveFrom
有无效参数!!!总共就两个参数,所以我又把Receive
函数改成下面这样!
public override bool Receive(ref byte[] buffer)
{
base.Receive(ref buffer);
byte[] recvBuffer = new byte[1024];
serverEnd = new IPEndPoint(IPAddress.Any, 0);
int len = MainSocket.ReceiveFrom(recvBuffer, ref serverEnd);
return len > 0;
}
结果运行的时候还是一样的报错!
然后我就跑去google以下,有人说要bind以下,然后我把Connect
函数改了~
public override bool Connect(string url, int port, double timeout=5000){
var MainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
EndPoint RemoteAddress = new IPEndPoint(IPAddress.Parse(url), port);
ThreadStart childref = new ThreadStart(this.ReceiveRun);
receiveThread = new Thread(childref);
receiveThread.Start();
string ip4 = "";
IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
foreach (var ipp in ips)
{
if (ipp.AddressFamily == AddressFamily.InterNetwork)
ip4 = ipp.ToString();
}
var localAddress = new IPEndPoint(IPAddress.Parse(ip4), 6001);
MainSocket.Bind(localAddress);
NetPackage package = new NetPackage();
package.Head.Protocol = 1001;
var bytes = package.Encode();
MainSocket.SendTo(bytes, RemoteAddress);
}
结果更惨,有多了一个错误!说是SendTo
的地址无效!
SocketException: 在其上下文中,该请求的地址无效。
System.Net.Sockets.Socket.SendTo (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) (at <743b6648c9264b5cabe5d91045f6e132>:0)
System.Net.Sockets.Socket.SendTo (System.Byte[] buffer, System.Net.EndPoint remoteEP) (at <743b6648c9264b5cabe5d91045f6e132>:0)
WDFramework.UdpNetDriver.Connect (System.String url, System.Int32 port, System.Double timeout) (at Assets/Framework/Runtime/Network/UdpNetDriver.cs:38)
UILoginView.OnEnable () (at Assets/Scripts/Login/UILoginView.cs:16)
UnityEngine.GameObject:SetActive(GameObject, Boolean)
WDFramework.ViewProcessor:BindOrUnbindView() (at Assets/Framework/Runtime/UISystem/ViewProcessor.cs:170)
WDFramework.ViewProcessor:OnUpdate() (at Assets/Framework/Runtime/UISystem/ViewProcessor.cs:107)
WDFramework.UISystem:Update() (at Assets/Framework/Runtime/UISystem/UISystem.cs:162)
我就想是不是参数不完整导致,就试一下把SendTo
的参数补全。
MainSocket.SendTo(bytes, bytes.Length, SocketFlags.None, RemoteAddress);
结果完全没有变化!
到此就只能再继续google了~
然后发现有人说要sendto
后再监听receivefrom
才不会有问题!然后我调整一些线程在sendto
后再Start
。
结果:完全没有问题了!
再逐步吧之前的Bind
和Sendto
补全删掉,都没有问题!
结论
udp的时候需要先SendTo
后再使用线程receivefrom
就没有问题!
PREVIOUSAddressable的Lua加载优化
NEXTunreal的几个数据类型的反射