我正在编写客户端/服务器应用程序,但实际上找不到符合我需要的指南。在我开始之前,我自己做这件事会让我遇到许多设计缺陷。例如,服务器应该每秒多次更新每个客户端的状态。我假设我不能单独更新每个客户端,但UDP广播应该解决这个问题。但是我仍然需要一个TCP通道来与每个客户端可靠地通信,例如:聊天消息,用户输入等。
研究这个主题似乎服务器可以同时使用这两种协议 - 但只能是可能的(不是敏感的)。没有人建议采用这种方法,事实上我从this article收集到使用这两种方法相当糟糕。
现在我对如何处理服务器中的数据非常困惑。除非我完全误解了丢包的内容,否则我想保证导致'server-request-packets'的用户输入不会丢失。关于保证使用UDP传递的所有关于SO的答案都说使用TCP。更令人沮丧的是,我能想象到的每个服务器/客户端程序至少需要保证传递的一些消息(例如'disconnect'消息?)。
我应该使用UDP,TCP,还是我只是在想这个?
答案 0 :(得分:15)
让我们了解一下事实:
UDP不可靠。如初。
在某些情况下,UDP可能特别有损;例如如果存在网络拥塞,速率限制或流量分析,或者UDP消息大小大于MTU。
UDP广播仅适用于您的本地网段。互联网路由器通常不允许广播进一步传播。这确实限制了它的用处。
UDP组播可能是可能的,除了那些也容易被阻止。
所以这可能会让你有两个主要的可能性:
另一种可能性是使用UDP或TCP的某种对等网状通信,但这变得非常复杂。除非你真的需要,并且真的知道你在做什么,否则不要去那里。
那么你的问题。
我应该使用UDP,TCP,还是我只是在想这个?
我建议在服务器和每个客户端之间使用TCP,因为它最简单。为了进一步简化,每个客户端使用多个TCP连接,以避免多路复用多个#34;会话的复杂性。一个插座。
网络性能不是最优的,但它可能足够好你的应用程序。我怀疑这是您希望花费所有开发人员时间的应用程序的一部分。
当你到达工作应用程序(客户端和服务器端)并且有人使用它时,你可能会发现(或不是!)网络是一个主要的瓶颈和用户不满的原因。然后,您将看看如何优化应用程序2.0版中的通信。
当您实现版本2.0(或3.0 ...)以解决可伸缩性问题时,您需要从依赖单个服务器的方式开始。简而言之,如果你有N个客户,并且N不断增加,那么在某个时刻单个服务器无法应对。应用程序设计中的其他内容也可能存在问题。例如,在游戏应用程序中,您无法向所有其他玩家发送有关每个玩家的持续更新...其中玩家数量不断增长。但请注意,这些问题在很大程度上与您使用的网络协议无关。
答案 1 :(得分:6)
..但UDP广播应该解决这个问题
仅在本地网络内部进行广播工作,并且相关的多播需要基础设施的支持 - 这不是一件容易的事。
除此之外:" ...编写客户端/服务器应用程序没有一般规则......"。通信方法和协议在很大程度上取决于用例,范围从简单的UDP或TCP数据包到复杂的消息传递体系结构,具有可靠性和实时保证等。
因此,你需要做的事情取决于你想要达到的目标,而你没有详细说明。
答案 2 :(得分:1)
忘记广播协议,它们只是不像有人已经写过的那样工作。您需要将消息传递给每个客户端,创建一个类StateChangeDispatcher或类似的东西。
UDP不可靠但速度比TCP快,特别是考虑到没有握手。握手不仅速度慢,而且占用带宽也很少,特别是当您必须与许多客户建立连接时。
使用UDP和TCP并不是那么糟糕,很多着名的程序都采用这种方法。例如,BitTorrent可以使用两种协议:UDP用于与跟踪器通信,以及管理DHT和TCP以传输大量文件。这是我对他们选择的解释:跟踪器或DHT定期被查询,这意味着在使用的一天内你可以更新你的跟踪器数百次,如果有些时候不起作用并不是什么大不了因为你是无论如何都会在下次更新跟踪器时(同样的想法是在DNS协议中,您通过UDP发送请求,如果您在合理的时间内没有收到响应,则只需重新发送请求)。相反,TCP协议必须用于文件传输,因为您希望速度更慢但是您需要绝对的可靠性。
使用这两种协议的另一个着名应用是Skype,但原因各不相同。 videocalls是UDP,这是因为TCP协议在收到错误的数据包时停止并再次请求数据包,这需要时间。所以最好不要停止呼叫,而是接收和处理错误的数据包。这就是为什么在skype你有时收到一个糟糕的视频或难以理解的音频,你可以接收视频,因为它是录音机,但它太慢了。 TCP用于发送文件等其他内容。
所以你必须每秒多次向很多客户发送消息。我不会在每条消息上建立新的TCP连接。 在我看来,你有两个选择:
使用两个TCP连接的着名协议是FTP,你有一个连接发送命令并接收对服务器的响应,一个连接发送和接收文件,回想一下你没有建立每个命令的连接,即使命令可以在很短的时间间隔内发送(肯定会在一秒钟内多次发送),以避免过多的握手。 您可以遵循许多模式,但请注意测试协议很昂贵(您需要大量时间,并且可能需要10台以上的计算机才能查看是否一切正常)所以在开始编码之前要好好思考,在互联网上你可以找到一些计算协议性能和带宽使用的数学方法,但它们并不是很简单。祝你好运。
答案 3 :(得分:0)
您要求的相同原则用于DNS服务器。 DNS通常使用UDP来快速传输(UDP协议的原理),但不可靠。 TCP速度较慢(使用ACK和有效负载),但可靠。因此,正如我在下面的仪式,使用两者,区分有效载荷。
来自DNS BIND文档:
通常,普通查询使用UDP,区域传输使用TCP。
但是,DNS将UDP查询和响应限制为大约500字节。如果 响应将大于该响应,服务器最多发回500 bytes并设置“truncated”标志。然后客户端应该这样做 使用TCP再次执行相同的查询,这几乎是无限的 它可以发送的响应大小......
如果您想一次更新所有服务器,请将它们注册到MULTICAST,然后通过一个进程与所有客户端服务器进行通信。它再次不可靠,但速度很快。 https://en.wikipedia.org/wiki/IP_multicast 因此,您创建服务器,多播合作伙伴将注册到该服务器并从中进行监听。为了确保您检测到UDP数据报正在路由中丢弃,每个UD数据报都有其ID号。请确保您也可以按发送顺序接收数据报,因此应使用BUFFER或QUEUE,计算正确的顺序。
希望有所帮助。
答案 4 :(得分:0)
如果它是像动作游戏一样的客户/服务器游戏,我推荐你使用TCP作为用户界面,你不想放弃用户数据,但是在游戏中你无法承担TCP中的通信快速动作多人游戏。
因为失去了一些"动作游戏中的信息并不坏,所以我建议在游戏中使用UDP,或者在需要非常快速通信的地方推荐。
但如果不是需要快速沟通的游戏,我建议您使用TCP。
答案 5 :(得分:0)
在我看来,您正在考虑用于客户端/服务器通信的可靠方法,它将像没有开销TCP / IP通信的广播一样。
我也可以使用Messaging。创建消息驱动器bean(或消息客户端,concumer),它将注册到消息通道或消息队列,并将在PUSH方法上激活。
您的消息生产者会创建一条消息,并且将通知所有其他已注册的客户端服务器(消费者)并异步处理它。 您可以使用任何平台,也可以使用开源apache MQ。 https://en.wikipedia.org/wiki/Message_queue