首页 文章

无法附加到UDP侦听器C#中的接收字符串

提问于
浏览
6

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

当我打印所提供数据的字符串后,在转换byte []之后,从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);
}

    }

1 回答

  • 4

    我能想到的最简单的repro是这个代码:

    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数组中的poison-pill,它是0x00字节的存在导致输出字符串被缩短 . 超出该字节的任何内容都使其进入Visual Studio Output窗口 .

    解释这种行为需要深入了解Winforms应用程序中的Console.Write()如何工作以及它如何生成输出,即使您的程序没有控制台 . 这是一个冗长的故事,对于短版本而言并非如此 . 启用Visual Studio Hosting Process调试器选项后,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正确转换的可打印文本 .

相关问题