为什么我的编码显示两次?

时间:2014-08-02 16:42:34

标签: c# sockets utf-8 tcp

byte[] lengthBytes = new byte[4];
serverStream.Read(lengthBytes, 0, 4);
MessageBox.Show("'>>" + System.Text.Encoding.UTF8.GetString(lengthBytes) + "<<'");
MessageBox.Show("Hello");

这是我用于调试的代码。我现在收到2个留言箱。如果我使用Debug.WriteLine,它也会打印两次。

Msgbox 1: '>>/   (Note that this is still 4 characters long, the last 3 bytes are null.
Msgbox 2: '>>{"ac<<'
Msgbox 3: Hello

我正在尝试使用整数(消息的长度)发送4个字节。这很好('/'是47的utf8)。问题是消息的前4个字节也被读取('{“ac')。我完全不知道这是怎么发生的,我已经调试了几个小时了,我只是无法理解我的一个朋友建议在StackOverflow上创建一个帐户,所以我在这里:p

感谢所有帮助:)

编辑:询问

的人的真实代码

My code http://kutj.es/2ah-j9

3 个答案:

答案 0 :(得分:2)

你正在制造传统的程序员错误,每个人都必须做一次,以学习如何避免和正确行事。这主要是通过编写有缺陷的调试代码并使 lot 更难找到错误来实现的:

  • 从不编写使用MessageBox.Show()的调试代码。这是一个非常非常邪恶的功能,它会导致 re-entrancy 。而昂贵的单词意味着它只会冻结用户界面,它不会冻结您的程序。它继续运行,其中一个可能出错的事情是您发布的代码再次执行。重新输入。您将看到两个消息框。并且您的程序状态已完全损坏,因为您的代码从未被编写为假设可以重新输入。这就是为什么你抱怨吞下了4个字节的数据。

这里使用的正确工具是真正冻结程序的功能。调试器断点。

  • 从不假设二进制数据可以转换为文本。您收到的那4个字节包含二进制零。它没有任何特征。更糟糕的是,它充当许多操作系统调用的字符串终止符,调试器使用的类型,Debug.WriteLine()等。这就是为什么你看不到&#34;&lt;&lt;&#34 ;

这里使用的正确工具是调试器手表或工具提示,它可以让您直接查看数组。如果您必须生成诊断字符串,请使用BitConverter.GetString()。

  • 从不假设流的Read()方法将始终返回您要求的字节数。在代码中使用返回值是一项艰难的要求。这是您程序中的真正错误,也是您实际尝试修复的唯一错误。

正确的解决方案是继续调用Read(),直到您倒计数您希望从之前读取的 length 接收的字节数。你需要一个MemoryStream来存储你得到的byte []的块。

答案 1 :(得分:1)

关于Encoding.GetString()的this link可能会帮助你。要注意的部分是:

  

如果要转换的数据仅在顺序块中可用   (,例如从流中读取的数据)或者数据量是否过大   它需要分成更小的块,你应该使用   由派生类的GetDecoder方法返回的解码器对象。

答案 2 :(得分:1)

问题是我启动了getMessage void 2次。这开始了2次(在不同的线程中)。

埃尔贡佐帮助我找到了问题,他是个好人:)