我正在写一个UDP服务器,这对我来说是第一个;我只做了一点TCP通信。而且我无法确定如何区分哪个用户是哪个,因为UDP只处理数据包而不是连接,因此我无法确切地告诉我与谁通信。
这是我当前服务器循环的伪代码:
DatagramPacket p;
socket.receive(p); // now p contains the user's IP and port, and the data
int key = getKey(p);
if(key == 0) { // connection request
key = makeKey(p);
clients.add(key, p.ip);
send(p.ip, p.port, key); // give the user his key
} else { // user has a key
// verify key belongs to that IP address
// lookup the user's session data based on the key
// react to the packet in the context of the session
}
在设计时,我牢记这些要点:
第三个假设是否正确,或者我可以简单地假设一个用户=一个IP +端口组合?这是常见的,还是应该继续创建一个像我目前正在做的特殊键?
我不完全清楚TCP如何协商连接,所以如果你认为我应该用TCP建模它,那么请把我链接到一个很好的教程或TCP的SYN / SYNACK / ACK混乱。
另请注意,如果IP发送0并且该IP已有挂起密钥,我确实有重新发送密钥的规定;我省略了它以保持代码片段简单。我知道UDP不能保证到达,我计划稍后为主数据包处理代码增加可靠性。
答案 0 :(得分:7)
UDP数据包标头有一个源端口,通常用作应答端口。如果不使用,它应该为零,然后由更高级别的协议决定如何协调多个客户端的请求 - 响应活动。
答案 1 :(得分:2)
您的问题只是使用UDP时需要注意的冰山WRT清单上的一小部分问题。您应该期望NAT路由器无法提供您设计的UDP协议的任何有意义的转发。 TCP有效,因为路由器了解TCP状态机并存储每个会话的连接状态,因此他们知道如何转发它。他们将不知道您的自定义UDP协议如何工作。 NAT设备包括用于众所周知的UDP应用的特定协议处理程序。
如果发件人绑定到源端口和/或接口,则发件人源端口在未绑定之前保持不变。
使用UDP,您可以将两个对等体绑定到(dst)传入和/或(src)传出消息的已知源端口。对于客户端/服务器应用程序,您通常希望客户端绑定到动态源端口,以便多个客户端可以在单个客户端系统上共存。然后,服务器可以使用通过src端口提供的动态源端口响应客户端,该请求用作响应中的目标端口。使用已知的对等端口允许您在NAT设备中配置UDP转发。
在已知端口3000上具有服务器的客户端/服务器
客户端绑定到随机端口(1234)但知道服务器正在侦听端口3000。 客户(src 1234) - >服务器(dst 3000) 服务器(dst 1234) - >客户端(src 3000) ...
如果计算机有多个接口,您应该要么需要将侦听器或发送器显式绑定到特定的IP地址,要么能够处理来自正在发送和从随机IP <接收的对等方的请求和响应/ em>基于计算机路由表的奇思妙想。如果您选择将请求绑定到特定接口,那么如果来自多宿主系统的消息需要传输不同的本地接口以进行传递,则需要了解路由表。例如,如果将UDP套接字绑定到127.0.0.1,则显然无法使用它发送到任何可路由的可路由IP地址。
在协议设计方面,它通常用于在UDP有效载荷中构建会话ID和序列字段,以便对等体可以跟踪会话和单个交换。
为了成功设计强大的UDP协议,您需要了解一大堆碎片,NAT共存,安全和拥塞问题。除非绝对必要,否则我会反对。
答案 2 :(得分:2)
* The outbound port on the client side might change among packets.
第三个假设是否正确
如果客户端继续使用相同的出站套接字,则不行。发送第一个数据报将导致本地绑定,因此从那时起套接字将位于固定的本地端口上。