我正在尝试为我正在开发的游戏编写通用套接字服务器。我知道我可以很好地使用 SmartFox 和 Photon 等已经构建的服务器,但我不想经历为学习目的而自己创建一个服务器的痛苦。
我提出了一个受 BSON 启发的协议,将基本数据类型、它们的数组和特殊的 GSObject 转换为二进制,并以某种方式排列它们,以便可以在客户端将它们重新组合成对象形式。在核心,转换方法利用 .Net BitConverter 类将基本数据类型转换为二进制。无论如何,问题在于性能,如果我循环 50,000 次并将我的 GSObject 转换为二进制每次大约需要 5500 毫秒(每次转换的结果 byte[] 仅为 192 个字节)。我认为这对于一个每秒发送 5-10 个位置更新和 1000 个并发用户的 MMO 来说太慢了。是的,我知道一款游戏不太可能同时拥有 1000 个用户,但就像我之前所说的,这对我来说应该是一个学习过程,
所以是的,如果有人知道其他转换技术或看到我在哪里失去性能,我将不胜感激。
GSBitConverter.cs
这是主要的转换类,它为主要数据类型添加了扩展方法以转换为二进制格式。它使用 BitConverter 类来转换基本类型。我只展示了转换整数和整数数组的代码,但该方法的其余部分几乎是这两者的复制品,它们只是重载了类型。
public static class GSBitConverter
{
public static byte[] ToGSBinary(this short value)
{
return BitConverter.GetBytes(value);
}
public static byte[] ToGSBinary(this IEnumerable<short> value)
{
List<byte> bytes = new List<byte>();
short length = (short)value.Count();
bytes.AddRange(length.ToGSBinary());
for (int i = 0; i < length; i++)
bytes.AddRange(value.ElementAt(i).ToGSBinary());
return bytes.ToArray();
}
public static byte[] ToGSBinary(this bool value);
public static byte[] ToGSBinary(this IEnumerable<bool> value);
public static byte[] ToGSBinary(this IEnumerable<byte> value);
public static byte[] ToGSBinary(this int value);
public static byte[] ToGSBinary(this IEnumerable<int> value);
public static byte[] ToGSBinary(this long value);
public static byte[] ToGSBinary(this IEnumerable<long> value);
public static byte[] ToGSBinary(this float value);
public static byte[] ToGSBinary(this IEnumerable<float> value);
public static byte[] ToGSBinary(this double value);
public static byte[] ToGSBinary(this IEnumerable<double> value);
public static byte[] ToGSBinary(this string value);
public static byte[] ToGSBinary(this IEnumerable<string> value);
public static string GetHexDump(this IEnumerable<byte> value);
}
Program.cs 这是我在循环中转换为二进制的对象。
class Program
{
static void Main(string[] args)
{
GSObject obj = new GSObject();
obj.AttachShort("smallInt", 15);
obj.AttachInt("medInt", 120700);
obj.AttachLong("bigInt", 10900800700);
obj.AttachDouble("doubleVal", Math.PI);
obj.AttachStringArray("muppetNames", new string[] { "Kermit", "Fozzy", "Piggy", "Animal", "Gonzo" });
GSObject apple = new GSObject();
apple.AttachString("name", "Apple");
apple.AttachString("color", "red");
apple.AttachBool("inStock", true);
apple.AttachFloat("price", (float)1.5);
GSObject lemon = new GSObject();
apple.AttachString("name", "Lemon");
apple.AttachString("color", "yellow");
apple.AttachBool("inStock", false);
apple.AttachFloat("price", (float)0.8);
GSObject apricoat = new GSObject();
apple.AttachString("name", "Apricoat");
apple.AttachString("color", "orange");
apple.AttachBool("inStock", true);
apple.AttachFloat("price", (float)1.9);
GSObject kiwi = new GSObject();
apple.AttachString("name", "Kiwi");
apple.AttachString("color", "green");
apple.AttachBool("inStock", true);
apple.AttachFloat("price", (float)2.3);
GSArray fruits = new GSArray();
fruits.AddGSObject(apple);
fruits.AddGSObject(lemon);
fruits.AddGSObject(apricoat);
fruits.AddGSObject(kiwi);
obj.AttachGSArray("fruits", fruits);
Stopwatch w1 = Stopwatch.StartNew();
for (int i = 0; i < 50000; i++)
{
byte[] b = obj.ToGSBinary();
}
w1.Stop();
Console.WriteLine(BitConverter.IsLittleEndian ? "Little Endian" : "Big Endian");
Console.WriteLine(w1.ElapsedMilliseconds + "ms");
}
这是上面代码中使用的一些其他类的代码。大部分都是重复的。