System.IO.Compression を使用して自分でメッセージを圧縮することもできます (以下の util を参照してください - 拡張子として追加するだけです)。
しかし、キューイング/スロットリングの質問について。大きなメッセージは常に、小さな/最適化されたチャンクよりもネットワークから遅れます。50k 以下のデータを分割するか、udp を使用できる場合、tcp よりも少ないキューイングと検証でより高速に送信できます。
TCP パケット サイズの絶対的な制限は 64K (65535 バイト) ですが、実際には、下位層 (イーサネットなど) のパケット サイズが小さいため、これは表示されるパケットのサイズよりもはるかに大きくなります。
たとえば、イーサネットの MTU (Maximum Transmission Unit) は 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;
}
}
}