服务器UDP和端口绑定

时间:2012-01-04 18:19:29

标签: java networking udp

我用Java编写这个游戏,并且在网络架构方面存在问题。

我决定使用UDP数据包。我刚刚开始,但我面临的问题是,似乎服务器必须从完全相同的IP /端口响应客户端(在使用NAT的路由器后面)作为客户端连接该服务器。

例如我在路由器后面有客户端A.客户端A具有IP(本地)192.168.8.100,它将服务器B与端口1234连接。服务器位于11.11.11.11:2345。

当客户端A连接到服务器B时,它使用192.168.8.100:1234但路由器将其转换为(例如)22.22.22.22:6789。

现在,当服务器想要向该客户端发送数据包时,它必须来自11.11.11.11:2345。 我想从另一个端口发送数据,如11.11.11.11:2222,但这似乎不起作用,至少不能用我的路由器。

我想使用不同的端口,因为我希望有两个线程用于监听,一个用于发送数据,每个线程都有自己的DatagramSocket。但是,正如我所说,一旦客户端A连接到端口2345上的服务器,我就无法从端口2222发送数据。

有谁知道这是如何处理的?我是用Java做的,但它并不是特定于语言的问题。

更新

@Perception评论后,我对他的评论有了更多疑问:

好的,所以如果我理解正确的话,如果我有服务器主办1000个游戏,每个游戏有2个玩家,所有发送/接收都必须通过相同的DatagramSocket完成。

据我所知,DatagramSocket是线程安全的所以我想我可以有一个线程在做:

datagramSocket.receive();

同时第二个线程在做

datagramSocket.send(.....);

正确?

另外,两个线程可以通过同一个DatagramSocket同时发送数据吗?是以串行方式发送的,这意味着第二个send()只在前一个send()完成后才启动,或者是同时发送数据?

2 个答案:

答案 0 :(得分:0)

gorann,我不确定我是否正确理解你,但听起来你正试图控制服务器与客户端通信的端口。没有办法控制这个,并且有充分的理由。

答案 1 :(得分:0)

这是TCP和UDP之间比较棘手的差异之一。

当启动新的TCP会话时,服务器端调用accept()会为您提供一个新的套接字,操作系统会为您处理多个会话的多路复用。使用UDP,您需要自己处理多路复用。但您需要以与NAT和其他防火墙一起使用的方式执行此操作。

NAT的工作方式是,当它看到一个外发数据包时,会创建一个临时规则允许数据包沿同一个端口对返回。从客户端尚未发送到的端口返回的数据可能会被阻止。

这为您提供了两个选择:

  1. 您可以通过单个端口完成所有通信。这不是一个糟糕的选择,它只是意味着您需要一种方法来识别客户端会话并将它们路由到适当的线程。

  2. 您可以创建一个单独的端口,并指示客户端发送到该端口。让服务器监听固定端口。客户端向那里发送消息,然后服务器设置一个新的会话端口,并使用服务器的监听端口将该号码发送回客户端。然后,客户端向会话端口发送消息,这会导致NAT打开该端口并允许返回流量。现在客户端和服务器线程有自己的专用端口对。

  3. 选项1更有用,因为它需要在线程之间交换数据,但它会更好地扩展。选项1更容易,CPU效率更高,因为每个会话线程可以是独立的,但是有可用的端口数量有限。

    无论哪种方式,我建议您让客户端在每个数据包中包含一个半唯一的会话ID,以便服务器不仅仅包含客户端地址和端口号,以验证谁属于每个会话。