Rob*_*erk 6 string multithreading asynchronous udp beginreceive
我有一个创建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);
}
}
Run Code Online (Sandbox Code Playgroud)
我能想到的解决这个问题的最简单的重现是这段代码:
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");
}
Run Code Online (Sandbox Code Playgroud)
点击按钮几次后的输出:
HelHelHelHel
Run Code Online (Sandbox Code Playgroud)
您现在肯定认识到了receiveBytes数组中的毒丸,正是 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");
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)
或者您可能想更好地查看您传输的数据,确保它实际上是可打印文本,可以使用 Encoding.ASCII 正确转换