C# 索引超出范围,位于;int-msgLength=BitConverter.ToInt32(gzBuffer,0)&引用;
我目前正在制作一些用C#XNA制作的游戏。 因为我需要通过网络发送大量数据(大约96kb),所以我使用了一些字符串压缩程序/解压缩程序代码,这是我在互联网上找到的。 代码如下所示:C# 索引超出范围,位于;int-msgLength=BitConverter.ToInt32(gzBuffer,0)&引用;,c#,networking,xna,bitconverter,outofrangeexception,C#,Networking,Xna,Bitconverter,Outofrangeexception,我目前正在制作一些用C#XNA制作的游戏。 因为我需要通过网络发送大量数据(大约96kb),所以我使用了一些字符串压缩程序/解压缩程序代码,这是我在互联网上找到的。 代码如下所示: public static string Compress(string text) { byte[] buffer = Encoding.UTF8.GetBytes(text); MemoryStream ms = new MemoryStream();
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
返回一个空字节数组,但是在您知道接收到的字符串之前,很难取得任何进展。坚持Debug.Assert(gzBuffer.Length>=4);在调用BitConverter.ToInt32()之前,您将看到问题所在。gzBuffer甚至不包含读取Int32的4个字节。嗨,Jon Skeet,我尝试了你的建议,记录发送的字符串。原来客户机没有收到任何东西,所以我想我需要处理发送。谢谢你的帮助:)