在 UDP 上接收的 C# 数据总是无用的
本文关键字:数据 无用 UDP | 更新日期: 2023-09-27 18:33:04
这是我的问题;我正在尝试制作一个 UDP 服务器 - 客户端交互作为测试。我希望客户端将数据发送到服务器,如果服务器与服务器保存的数据匹配,它会发送回复。很简单,对吧?下面是一些代码:
客户端发送/接收代码:
void TestUDP()
{
Socket sock_addr = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint srver_endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 36);
string numbers = "1.2.3.4";
byte[] srver_req = Encoding.UTF8.GetBytes("TEST|" + numbers);
sock_addr.SendTo(srver_req, srver_endpoint);
EndPoint ref_endpoint = (EndPoint)srver_endpoint;
byte[] req_reply = new byte[1000];
sock_addr.ReceiveFrom(req_reply, ref ref_endpoint);
string reply = Encoding.UTF8.GetString(req_reply).Trim();
string[] s_str = reply.Split('|');
if (s_str[0] == "HEY")
{
MessageBox.Show("HEY");
}
else
{
MessageBox.Show("NO");
}
}
现在一些服务器代码:
public void start()
{
udp_sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
udp_sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
udp_thr = new Thread(udpListen);
udp_thr.Start();
}
void udpListen()
{
byte[] data = new byte[1024];
IPEndPoint ip = new IPEndPoint(IPAddress.Any, 36);
udp_sock.Bind(ip);
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint Remote = (EndPoint)(sender);
while (true)
{
udp_sock.ReceiveFrom(data, ref Remote);
Parse(data, Remote);
}
}
void Parse(byte[] data, EndPoint Remote)
{
string decData = Encoding.UTF8.GetString(data).Trim();
string[] s_str = decData.Split('|');
byte[] sendBuffer = new byte[] { };
switch (s_str[0])
{
case "TEST":
string data1 = s_str[1];
if (data1 == "1.2.3.4")
{
sendBuffer = Encoding.UTF8.GetBytes("HEY|");
}
else if(data1 != "1.2.3.4")
{
sendBuffer = Encoding.UTF8.GetBytes("NO|");
}
udp_sock.SendTo(sendBuffer, Remote);
break;
}
}
现在的问题是,它总是说"不",我不知道为什么。对我来说,这看起来应该有效,我做错了什么??我已经把这个套接字放到了广播上,因为我也想用这个处理广播请求。这是个问题吗?
首先,您应该添加诊断来打印出实际数据,而不仅仅是知道它是"对"还是"错"。
接下来,实际问题是您忽略了udp_sock.ReceiveFrom
的结果。这将告诉您实际接收了多少字节。目前,您始终将所有 1024 字节转换为字符串...这意味着您可能拥有刚刚收到的尾随数据。仅仅使用Trim()
并不是解决这个问题的好方法。 Trim()
不将 U+0000 计为空格,即使这样做,它仍然不是一个合适的方法 - 除了其他任何事情,您稍后会重用相同的缓冲区,因此如果您收到一条长消息,然后收到一条较短的消息,您最终会得到混合。
你想要:
// TODO: Fix your variable names, which are inconsistent non-idiomatic
int bytesRead = udp_sock.ReceiveFrom(data, ref Remote);
Parse(data, bytesRead, Remote);
并将Parse
更改为:
void Parse(byte[] data, int bytesRead, EndPoint remote)
{
string text = Encoding.UTF8.GetString(data, 0, bytesRead);
...
}
您需要在客户端和服务器上执行此操作。
此外,鉴于 if
/else
的第一个分支检查data1
是否为"1.2.3.4",您无需检查它是否不是。