6

我有一个创建 UDP 对象的表单,在 UDP 类中创建了一个 UDPClient,并使用 EndReceive 在 BeginReceive 方法中完成接收数据。

当我从 beginreceive 方法中打印接收数据的字符串后,将字节 [] 转换到控制台,并附加文本,只有接收到的数据打印不附加文本。

所以看起来接收到的数据不完整。

打印字符串时,不会显示 NewLine 和附加的“done”。

任何帮助都会很棒!

谢谢

class Udp
{
    public EventHandler _dataReceived;

    public Udp()
    {

        int receiverPort = 1248;
        UdpClient receiver = new UdpClient(receiverPort);

        string discovery = "<?xml version=\"1.0\"?><ServiceQuery></ServiceQuery>";

        receiver.BeginReceive(new AsyncCallback( DataReceived), receiver);

        IPEndPoint end = new IPEndPoint(IPAddress.Broadcast, 1248);
        receiver.Send(Encoding.ASCII.GetBytes(discovery + "\0"), discovery.Length + 1, end);
}

private void DataReceived(IAsyncResult ar)
{
    UdpClient c = (UdpClient)ar.AsyncState;
    IPEndPoint receivedIpEndPoint = new IPEndPoint(IPAddress.Any, 1248);

    Byte[] receivedBytes = c.EndReceive(ar, ref receivedIpEndPoint);

    string receivedText = ASCIIEncoding.ASCII.GetString(receivedBytes);

    Console.WriteLine("\n");

    if(_dataReceived != null)
    {
        Console.Write(receivedIpEndPoint + ": " + receivedText + Environment.NewLine + "done");
       _dataReceived(receivedText, new EventArgs());
    }

    c.BeginReceive(new AsyncCallback(DataReceived), c);
}

    }    
4

1 回答 1

4

对于这个问题,我能想到的最简单的重现是这段代码:

    private void button1_Click(object sender, EventArgs e) {
        Byte[] receivedBytes = new byte[] { 0x48, 0x65, 0x6c, 0x00, 0x6c, 0x6f };
        string receivedText = Encoding.ASCII.GetString(receivedBytes);
        Console.Write(receivedText + ", you won't see this");
    }

多次点击按钮后的输出:

   HelHelHelHel

您现在肯定认出了receivedBytes数组中的毒丸,正是0x00 字节的存在导致输出字符串被缩短。超出该字节的任何内容都不会进入 Visual Studio 输出窗口。

解释这种行为需要深入了解 Winforms 应用程序中的 Console.Write() 是如何工作的,以及它如何能够生成输出,即使你的程序没有控制台。这是一个冗长的故事,不太可能让任何人开心,所以我会选择简短的版本。启用 Visual Studio 托管进程调试器选项后,Console.Write() 等效于 Debug.Write()。调试输出被 DefaultTraceListener 类截获,它调用OutputDebugString()以获取出现在调试器跟踪窗口中的文本。这些 winapi 函数采用 C 字符串,C 字符串以零结尾表示字符串的结尾。

有几种方法可以解决这个问题,程序员的方法是将 byte[] 数组内容转换为十六进制:

    Byte[] receivedBytes = new byte[] { 0x48, 0x65, 0x6c, 0x00, 0x6c, 0x6f };
    string receivedText = BitConverter.ToString(receivedBytes);
    Console.WriteLine(receivedText + ", you see this");

输出:

    48-65-6C-00-6C-6F, you see this
    48-65-6C-00-6C-6F, you see this
    48-65-6C-00-6C-6F, you see this

或者您可能想更好地查看您传输的数据,确保它实际上是可以使用 Encoding.ASCII 正确转换的可打印文本

于 2015-08-01T14:35:34.750 回答