فهرس من النطاق في "int msglength = bitConverter.toint32 (gzbuffer ، 0) ؛"
-
27-09-2019 - |
سؤال
أنا أعمل حاليًا على بعض الألعاب التي صنعت في C# XNA. نظرًا لأنني بحاجة إلى إرسال جزء كبير من البيانات عبر Net (Bout 96 كيلو بايت) ، فأنا أستخدم بعض كود ضاغط/إلغاء ضغط السلسلة ، الذي وجدته على الإنترنت. الرمز يشبه هذا:
public static string Compress(string text)
{
byte[] buffer = Encoding.UTF8.GetBytes(text);
MemoryStream ms = new MemoryStream();
using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
{
zip.Write(buffer, 0, buffer.Length);
}
ms.Position = 0;
MemoryStream outStream = new MemoryStream();
byte[] compressed = new byte[ms.Length];
ms.Read(compressed, 0, compressed.Length);
byte[] gzBuffer = new byte[compressed.Length + 4];
System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
return Convert.ToBase64String(gzBuffer);
}
public static string Decompress(string compressedText)
{
byte[] gzBuffer = Convert.FromBase64String(compressedText);
using (MemoryStream ms = new MemoryStream())
{
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 4, gzBuffer.Length - 4);
byte[] buffer = new byte[msgLength];
ms.Position = 0;
using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
{
zip.Read(buffer, 0, buffer.Length);
}
return Encoding.UTF8.GetString(buffer);
}
}
يعمل مثل هذا: - يقوم الخادم بضغط السلسلة باستخدام ضاغط السلسلة ، حيث بعد إرسالها إلى العميل. - يتلقى العميل السلسلة المضغوطة ، ويكسرها بحيث تكون قابلة للاستخدام.
الآن الجزء الغريب هو أن الرمز يعمل عندما أختبر اللعبة وحدها ، مما يعني أنني أقوم بتشغيل الخادم والعميل على نفس الجهاز. يعمل أيضًا عندما أختبر مع صديقي ، حيث يستضيف الخادم ، وأتصل. ولكن إنه لا يعمل مع صديقي عندما أستضيف الخادم ويتصل. عندما يتصل بالخادم الخاص بي ، يتلقى "فهرس خارج النطاق" في "int msglength = bitConverter.toint32 (gzbuffer ، 0) ؛".في بعض الأحيان يكون محظوظًا ويدخل ، لكنه يفشل في الغالب ويعيد هذا الخطأ. هل يمكن أن يكون الخادم لا يتم إرسال السلسلة بأكملها؟ أنا أستخدم Lidgren Gen3 لإرسال الشبكة ، ويتم إرسال السلسلة المضغوطة كـ netmsg.write (CompressedString) ؛
أيه أفكار :) ؟ شكرًا!
المحلول
أنت تقوم بنفس الافتراض غير الصحيح في أماكن متعددة: ذلك Stream.Read
سيعود جميع البيانات التي طلبتها في واحدة. أنت تتجاهل قيمة الإرجاع. لا تفعل ذلك ... من المسلم به أنه يجب أن يكون على ما يرام MemoryStream
S ، على افتراض أن هناك ما يكفي من البيانات ، قد ترغب في استخدام MemoryStream.ToArray
طريقة للتحويل إلى صفيف بايت.
الآن ، لم تظهر كيف يتلقى العميل السلسلة - من أين تحصل عليها؟
يجب عليك تسجيل السلسلة التي يرسلها الخادم ، والسلسلة التي يتلقاها العميل. هذه هي الخطوة الأولى المطلقة ، حتى تتمكن من معرفة ما إذا كانت البيانات قد تم الحفاظ عليها بالفعل.
أظن أن العميل يحاول إلغاء ضغط سلسلة فارغة - أي ذلك Convert.FromBase64
يعيد صفيف بايت فارغ - ولكن حتى تعرف السلسلة التي يتم استلامها ، من الصعب إحراز أي تقدم.