我已经看过谷歌的所有内容,甚至在Stack溢出,但我似乎无法找到我正在寻找的解决方案。我正在测试我的编程技巧,使用MonoGame for C#重新制作Pong,我正试图用UDP客户端和UDP服务器制作这个多人游戏。我将使用“完美的客户端 - 服务器模型”的想法,服务器处理所有计算,而游戏客户端只是从服务器接收数据并将其显示在屏幕上。不幸的是,我曾经遇到过编程UDP服务器的问题。我有一个循环,我收到一个数据报,而不是开始听另一个。我使用异步调用,因为在我看来,这对客户端和服务器最有效。 主代码看起来像这样:(我将删除不会影响CPU的位,并仅显示网络。)
static void Main()
{
//Initialize
Console.Title = "Pong Server";
Console.WriteLine("Pong Server");
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//Bind socket
EndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 25565);
Console.WriteLine("Binding to port 25565");
serverSocket.Bind(localEndPoint);
//Listen
Console.WriteLine("Listening on {0}.", localEndPoint);
//Prepare EndPoints
EndPoint clientEndPoint = new IPEndPoint(IPAddress.Any, 0);
//Recive Data...
rcvPacket = new byte[Data.Size];
serverSocket.BeginReceiveFrom(rcvPacket, 0, Data.Size, SocketFlags.None, ref clientEndPoint, new AsyncCallback(Receive), null);
}
然后在接收(IAsyncResult ar)方法:
static void Receive(IAsyncResult ar)
{
//Prepare EndPoints
EndPoint clientEndPoint = new IPEndPoint(IPAddress.Any, 0);
//End
int PacketSize = serverSocket.EndReceiveFrom(ar, ref clientEndPoint);
//<Handle Packet Code Here>
//Receive Loop
rcvPacket = new byte[Data.Size];
serverSocket.BeginReceiveFrom(rcvPacket, 0, Data.Size, SocketFlags.None, ref clientEndPoint, new AsyncCallback(Receive), null);
}
这段代码看起来是等待收到数据包,而不是监听另一个数据包,这将停止这个“侦听器”线程,这是异步的。无论如何,感谢您阅读我的问题,希望我能深究这一点。
哦顺便说一句,这是我的4个核心之一的图像被最大化了。 (是的,我正在调试它。)
答案 0 :(得分:1)
添加 Thread.Sleep(1)调用更新循环不仅修复了原始问题中的CPU使用率,而且还使更新循环中执行的代码表现得更好。在 while(alive)} {} 里面,我记录了已用时间和总时间,我插入了睡眠通话。
似乎需要至少1 。
static void Main(string[] args)
{
//Initialize
Console.Title = "Pong Server";
Console.WriteLine("Pong Server");
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//Bind socket
EndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 25565);
Console.WriteLine("Binding to port 25565");
serverSocket.Bind(localEndPoint);
//Listen
Console.WriteLine("Listening on {0}.", localEndPoint);
//Prepare EndPoints
EndPoint clientEndPoint = new IPEndPoint(IPAddress.Any, 0);
//Recive Data...
serverSocket.BeginReceiveFrom(rcvPacket, 0, Data.Size, SocketFlags.None, ref clientEndPoint, new AsyncCallback(ReceiveFrom), null);
//Initialize TimeSpans
DateTime Now = DateTime.Now;
DateTime Start = Now;
DateTime LastUpdate = Now;
TimeSpan EllapsedTime;
TimeSpan TotalTime;
//Create Physics Objects
Paddle1 = new Physics2D();
Paddle2 = new Physics2D();
Ball = new Physics2D();
//Loop
while (alive)
{
Now = DateTime.Now;
TotalTime = Now - Start;
EllapsedTime = Now - LastUpdate;
LastUpdate = Now;
Update(EllapsedTime, TotalTime);
//Add Sleep to reduce CPU usage;
Thread.Sleep(1);
}
//Press Any Key
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
答案 1 :(得分:-1)
来自MSDN文档:
您的回调方法应调用 EndReceiveFrom 方法。当您的应用程序调用BeginReceiveFrom时,系统将使用单独的线程来执行指定的回调方法,并且它将在EndReceiveFrom上阻塞,直到Socket读取数据或引发异常。如果希望在调用BeginReceiveFrom方法后阻止原始线程,请使用WaitHandle.WaitOne。如果希望原始线程继续执行,请在回调方法中调用T:System.Threading.ManualResetEvent上的Set方法。有关编写回调方法的其他信息,请参阅回调示例
根据我的理解,您在调用BeginReceiveFrom时直接创建回调线程。 因为你没有使用EndReceiveFrom,你执行回调线程,一次又一次地创建另一个线程......
使用EndReceiveFrom等待读取整个数据包,然后您的回调将重复并再次开始读取。注意线程安全我不知道你如何管理你的数据。
查看该帖子可能会有所帮助: Asynchronous TCP/UDP Server