我正在编写一个允许客户端登录的UDP应用程序。之后,他们的端点存储在列表中。
private void socket_Callback(IAsyncResult result_)
{
EndPoint remote = new IPEndPoint(IPAddress.Any, 0);
socket.EndReceiveFrom(result_, ref remote);
if (!listOfEndPoints.Contains(remote))
{
// registration process
// add it to list
listOfEndPoints.Add(remote)
}
else
{
// process packet
}
}
但是,有时客户端的NAT会为每个数据包分配不同的外部端点。如果注册数据包的源端点为12.34.56.78:1000,则该端点将添加到列表中。然后,如果同一客户端发送另一个数据包,则NAT将为其分配不同的端口,因此其源端点将为12.34.56.78:1001。 这导致服务器假设客户端未注册,并尝试将数据包作为注册处理。不用说这不起作用。
解决这个问题的一种方法是向客户端发送一个ID(如果它不是超级神秘的话,可以很容易地伪造)。但是,客户端必须将其添加到它发送到服务器的每个数据包中。 所以这样做是不太有效的。
有没有其他方法可以告知数据包来自与注册数据包相同的客户端?
答案 0 :(得分:3)
您绝对应该不使用UDP数据包的源IP地址和端口将其与逻辑连接相关联。如果您收到相同逻辑连接的新IP和端口,则应在每个数据包中包含连接的ID,并更新您响应的IP和端口。如果连接高压是一个问题,您可能需要实现某种形式的安全性,例如数据报中的安全校验和。
TCP处理与您的连接关联数据包。使用UDP,您必须自己将数据报与逻辑会话相关联。我不知道为什么你认为“这样做会不会非常有效”。
UDP的一个权衡是,如果你需要TCP提供的任何东西,你必须自己编写代码。
顺便说一句,我从未见过以这种方式移动的端口。您确定客户端代码没有损坏,可能会为它发送的每个数据报打开一个新的套接字。