【发布时间】:2011-09-14 19:38:16
【问题描述】:
我正在制作一款需要大量数据流量的游戏,例如 Positions(2D) 和许多其他数据。 我正在使用一个非常简单的类来帮助我监听 8080 端口(UDP),以及发送数据报的方法:
public static void SendToHostUDP(string Msg)
{
UdpClient udpClient = new UdpClient();
udpClient.Connect(Main.HostIP, 8080);
byte[] sdBytes = Encoding.ASCII.GetBytes(Msg);
udpClient.BeginSend(sdBytes, sdBytes.Length, CallBack, udpClient);
Main.UDPout += sdBytes.Length / 1000f;
}
public static void SendToClientUDP(string Msg, IPAddress ip)
{
UdpClient udpClient = new UdpClient();
udpClient.Connect(ip, 8080);
byte[] sdBytes = Encoding.ASCII.GetBytes(Msg);
udpClient.BeginSend(sdBytes, sdBytes.Length, CallBack, udpClient);
Main.UDPout += sdBytes.Length / 1000f;
}
public static void CallBack(IAsyncResult ar)
{
}
监听器类只是一个非常简单的类:
public class NetReciever
{
public TcpListener tcpListener;
public Thread listenThread;
private Action actionToPerformTCP;
private Action actionToPerformUDP;
public UdpClient udpClient;
public Thread UDPThread;
TimerAction UDPPacketsCounter;
int UDPPacketsCounts;
private BackgroundWorker bkgUDPListener;
string msg;
public NetReciever(IPAddress IP)
{
this.tcpListener = new TcpListener(IPAddress.Any, 25565);
this.udpClient = new UdpClient(8080);
this.UDPThread = new Thread(new ThreadStart(UDPListen));
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
UDPPacketsCounter = new TimerAction(CountUDPPackets, 1000, false);
this.UDPThread.Start();
}
public void CountUDPPackets()
{
UDPPacketsCounts = 0;
}
public void Abort()
{
UDPThread.Abort();
udpClient.Close();
listenThread.Abort();
tcpListener.Stop();
}
public void UDPListen()
{
while (true)
{
IPEndPoint RemoteIPEndPoint = new IPEndPoint(IPAddress.Any, 0);
byte[] receiveBytesUDP = udpClient.Receive(ref RemoteIPEndPoint);
if (receiveBytesUDP != null)
{
UDPPacketsCounts++;
Main.UDPin += receiveBytesUDP.Length / 1000f;
}
if (Main.isHost)
{
Main.Server.processUDP(Encoding.ASCII.GetString(receiveBytesUDP), RemoteIPEndPoint.Address.ToString());
}
else
{
if (RemoteIPEndPoint.Address.ToString() == Main.HostIP)
{
Program.game.ProcessUDP(Encoding.ASCII.GetString(receiveBytesUDP));
}
}
}
}
所以基本上当有 1 个玩家时,大约 60packet/s IN 和 60packet/s out。
它的作用是这样的:
- 监听数据包。
- 验证数据包。
- 处理数据包数据 -> 就像存储一些位置,发回一些数据包......
所以它只是像这样循环。
问题就在这里:
首先,当有 2 个玩家(主机 + 1 个客户端)时,在某些时候会出现一些显着的 FPS 下降,并且主机会经历片刻所有音频的卡顿(比如蓝屏)。
其次,当有2+玩家(Host + 1+Client)时,Host FPS会下降到5-20,并且会lag+lag+lag+lag但不会卡顿。
我读过一些关于异步的文章,这已经是线程化的了?
还有BeginRecieve 和EndRecieve,我真的不明白我如何以及为什么需要使用它。
能否提供一些示例来解释如何处理这些类型的数据并发送/接收数据包?我真的不想使用库,因为我想知道发生了什么。
P.S:泰拉瑞亚的网络系统是如何工作的?它使用 TCP,但它很流畅!怎么样?
PSS:什么是缓冲?为什么我需要设置缓冲以及如何设置?它有什么变化?
PSSS:我认为在发送数据包时需要调整和更改,因为它看起来很简单。
【问题讨论】:
-
“赢得比赛的唯一方法就是根本不玩。”您不应该用大量数据淹没网络 - 仅在值实际发生变化时发送数据。此外,使用速率限制和客户端预测来避免同样的问题。老实说,在 Google 上花 2 分钟就会告诉你这一点 - 并给你举个例子。
-
为什么你的回调是空的?至少你应该调用
udpClient.EndSend来完成异步操作。这和你昨天问的问题基本一样吗? -
什么是
ListenForClients?它不在您的代码中。
标签: c# networking xna