您可以尝试的一件事是通过 System.IO.Compression 自己压缩消息(请参阅下面的实用程序 - 您可以添加为扩展名)。
但是关于排队/节流问题。与较小/优化的块相比,较大的消息总是比网络滞后。如果您可以分解小于或等于 50k 或更少的数据或使用 udp,它可能会比在 tcp 上以更少的排队和验证传输更快。
TCP 数据包大小的绝对限制是 64K(65535 字节),但实际上这远远大于您将看到的任何数据包的大小,因为较低层(例如以太网)的数据包大小较小。
例如,以太网的 MTU(最大传输单元)为 1500 字节。某些类型的网络(如令牌环)具有较大的 MTU,而某些类型具有较小的 MTU,但对于每种物理技术,这些值是固定的。
从这里开始:TCP 连接的最大数据包大小
当你把事情分开时事情会变得更顺利,多人游戏已经这样做了,他们还更多地使用 udp 来限制额外的验证(实施可靠的 udp 来验证单个消息并仅在需要时进行排序)。
CompressionUtil 类,在发送前/接收后压缩消息进出:https ://gist.github.com/drawcode/8948293
public static class CompressUtil {
public static string ToCompressed(this string val) {
if (!IsStringCompressed(val)) {
return CompressString(val);
}
return val;
}
public static string ToDecompressed(this string val) {
if (IsStringCompressed(val)) {
return DecompressString(val);
}
return val;
}
public static string CompressString(string text) {
byte[] buffer = Encoding.UTF8.GetBytes(text);
var memoryStream = new MemoryStream();
using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, true)) {
gZipStream.Write(buffer, 0, buffer.Length);
}
memoryStream.Position = 0;
var compressedData = new byte[memoryStream.Length];
memoryStream.Read(compressedData, 0, compressedData.Length);
var gZipBuffer = new byte[compressedData.Length + 4];
Buffer.BlockCopy(compressedData, 0, gZipBuffer, 4, compressedData.Length);
Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gZipBuffer, 0, 4);
return Convert.ToBase64String(gZipBuffer);
}
public static string DecompressString(string compressedText) {
byte[] gZipBuffer = Convert.FromBase64String(compressedText);
using (var memoryStream = new MemoryStream()) {
int dataLength = BitConverter.ToInt32(gZipBuffer, 0);
memoryStream.Write(gZipBuffer, 4, gZipBuffer.Length - 4);
var buffer = new byte[dataLength];
memoryStream.Position = 0;
using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress)) {
gZipStream.Read(buffer, 0, buffer.Length);
}
return Encoding.UTF8.GetString(buffer);
}
}
public static bool IsStringCompressed(string data) {
if (IsStringCompressedGZip(data) || IsStringCompressedPKZip(data)) {
return true;
}
return false;
}
public static bool IsStringCompressedGZip(string data) {
return CheckSignatureString(data, 3, "1F-8B-08");
}
public static bool IsStringCompressedPKZip(string data) {
return CheckSignatureString(data, 4, "50-4B-03-04");
}
public static bool CheckSignatureFile(string filepath, int signatureSize, string expectedSignature) {
if (String.IsNullOrEmpty(filepath))
throw new ArgumentException("Must specify a filepath");
if (String.IsNullOrEmpty(expectedSignature))
throw new ArgumentException("Must specify a value for the expected file signature");
using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
if (fs.Length < signatureSize)
return false;
byte[] signature = new byte[signatureSize];
int bytesRequired = signatureSize;
int index = 0;
while (bytesRequired > 0) {
int bytesRead = fs.Read(signature, index, bytesRequired);
bytesRequired -= bytesRead;
index += bytesRead;
}
string actualSignature = BitConverter.ToString(signature);
if (actualSignature == expectedSignature)
return true;
else
return false;
}
}
public static bool CheckSignatureString(string data, int signatureSize, string expectedSignature) {
byte[] datas = Encoding.ASCII.GetBytes(data);
using (MemoryStream ms = new MemoryStream(datas)) {
if (ms.Length < signatureSize)
return false;
byte[] signature = new byte[signatureSize];
int bytesRequired = signatureSize;
int index = 0;
while (bytesRequired > 0) {
int bytesRead = ms.Read(signature, index, bytesRequired);
bytesRequired -= bytesRead;
index += bytesRead;
}
string actualSignature = BitConverter.ToString(signature);
if (actualSignature == expectedSignature)
return true;
else
return false;
}
}
}