首页 文章

我的服务器应该同时使用TCP和UDP吗?

提问于
浏览
11

我正在编写客户端/服务器应用程序,但实际上找不到符合我需要的指南 . 在我开始之前,我自己做这件事会让我遇到许多设计缺陷 . 例如,服务器应该每秒多次更新每个客户端的状态 . 我假设我不能单独更新每个客户端,但UDP广播应该解决这个问题 . 但是我仍然需要一个TCP通道来与每个客户端可靠地通信,例如:聊天消息,用户输入等 .

研究这个主题似乎服务器可以同时使用这两种协议 - 但只能是可能的(不是敏感的) . 没有人建议这样的方法,事实上我从this article收集到,使用两者都是相当糟糕的 .


现在我对如何处理服务器中的数据非常困惑 . 除非我完全误解了丢包的内容,否则我想保证导致'server-request-packets'的用户输入不会丢失 . 关于保证使用UDP传递的所有关于SO的答案都说使用TCP . 更令人沮丧的是,我能想象的每个服务器/客户端程序至少需要保证传递的一些消息(例如'disconnect'消息?) .

我应该使用UDP,TCP,还是我只是在想这个问题?

6 回答

  • 15

    让我们得到一些事实:

    • UDP不可靠 . 永远 .

    • 在某些情况下,UDP可能特别有损;例如如果存在网络拥塞,速率限制或流量分析,或者UDP消息大小大于MTU .

    • UDP广播仅适用于您的本地网段 . 互联网路由器通常不允许广播进一步传播 . 这确实限制了它的用处 .

    • UDP多播可能是可能的,除了那样也会被阻止 .

    所以这可能会让你有两个主要的可能性:

    • 从服务器到每个客户端的UDP点对点消息传递 .

    • TCP从服务器到每个客户端 .

    另一种可能性是使用UDP或TCP的某种对等网状通信,但这变得非常复杂 . 除非你真的需要,否则不要去那里,而且真的知道你在做什么 .

    所以对你的问题 .

    我应该使用UDP,TCP,还是我只是在想这个错误?

    我建议在服务器和每个客户端之间使用TCP,因为它最简单 . 为了进一步简化,每个客户端使用多个TCP连接,以避免在单个套接字中复用多个“对话”的复杂性 .

    网络性能不是最佳的,但它可能足够好你的应用程序 . 我怀疑这是您希望花费所有开发人员时间的应用程序的一部分 .

    当你到达工作应用程序(客户端和服务器端)并且有人使用它时,你可能会发现(或不是!)网络是一个主要的瓶颈和用户不满的原因 . 然后,您将了解如何优化应用程序2.0版中的通信 .

    当您实现版本2.0(或3.0 ...)以解决可伸缩性时,您将需要从依赖单个服务器的方式开始 . 简而言之,如果你有N个客户端,并且N不断增加,那么在某些时候单个服务器将无法应对 . 应用程序设计中的其他内容也可能存在问题 . 例如,在游戏应用程序中,您无法向所有其他玩家发送有关每个玩家的持续更新...其中玩家数量不断增长 . 但请注意,这些问题在很大程度上与您使用的网络协议无关 .

  • 1

    ..但UDP广播应该解决这个问题

    广播仅在本地网络内工作,相关的多播需要基础设施的支持 - 这不是微不足道的 .

    除此之外:“..编写客户端/服务器应用程序......”没有一般规则 . 通信方法和协议在很大程度上取决于用例,范围从简单的UDP或TCP数据包到复杂的消息传递体系结构,具有可靠性和实时性保证等 .

    因此,您需要做的事情取决于您要实现的目标,而您没有详细说明 .

  • 6

    忘记广播协议,他们只是没有像有人已经写过的那样工作 . 您需要将消息传递给每个客户端,创建类StateChangeDispatcher或类似的东西 .

    UDP不可靠,但比TCP快特别是考虑到没有握手 . 握手不仅速度慢,而且占用带宽也很少,特别是当您必须与许多客户 Build 连接时 .

    使用UDP和TCP并不是那么糟糕,很多着名的程序都采用这种方法 . 例如,BitTorrent可以使用两种协议:UDP用于与跟踪器通信,以及管理DHT和TCP以传输大量文件 . 这是我对他们选择的解释:跟踪器或DHT定期被查询,这意味着在使用的一天内你可以更新你的跟踪器数百次,如果有些时候不起作用并不是什么大不了因为你是无论如何都会在下次更新跟踪器时(同样的想法是在DNS协议中,您通过UDP发送请求,如果您在合理的时间内没有收到响应,则只需重新发送请求) . TCP协议必须用于文件传输,因为您希望更慢,但您需要绝对的可靠性 .

    使用这两种协议的另一个着名应用是Skype,但原因各不相同 . videocalls是UDP,这是因为TCP协议在收到错误的数据包时停止并再次请求数据包,这需要时间 . 所以最好不要停止呼叫,而是接收和处理错误的数据包 . 这就是为什么在skype你有时收到一个糟糕的视频或难以理解的音频,你可以接收视频,因为它是录音机,但它太慢了 . TCP用于发送文件等其他内容 .

    所以你必须每秒多次向很多客户发送消息 . 我不会在每条消息上 Build 新的TCP连接 . 在我看来,你有两个选择:

    当且仅当您能承受一些数据丢失时,

    • 才会通过UDP发送每个服务器的状态更改

    • 为每个客户端 Build 一个TCP连接,并使用该连接发送所有服务器的状态更改,而不是在客户端断开连接时关闭连接

    使用两个TCP连接的着名协议是FTP,您有一个连接发送命令并接收对服务器的响应,一个连接发送和接收文件,回想一下即使命令可以是每个命令都没有 Build 连接时间间隔很长(肯定会超过一秒钟),以避免过多的握手 . 您可以遵循许多模式,但请注意测试协议很昂贵(您需要大量时间,并且可能需要10台以上的计算机才能查看是否一切正常)所以在开始编码之前要好好思考,在互联网上你可以找到一些计算协议性能和带宽使用的数学方法,但它们并不是很简单 . 祝好运 .

  • 0

    在DNS服务器中使用与您要求相同的原理 . DNS通常使用UDP来快速传输(UDP协议的原理),但不可靠 . TCP速度较慢(使用ACK和有效负载),但可靠 . 因此,正如我在下面的仪式,使用两者,区分有效载荷 .

    来自DNS BIND文档:

    通常,普通查询使用UDP,区域传输使用TCP . 但是,DNS将UDP查询和响应限制为大约500字节 . 如果响应大于该响应,则服务器最多发送500个字节并设置“截断”标志 . 然后客户端应该使用TCP再次执行相同的查询,这几乎可以无限制地发送响应的大小......

    如果您想一次更新所有服务器,请将它们注册到MULTICAST,并通过一个进程与所有客户端服务器进行通信 . 它再次不可靠,但速度很快 . https://en.wikipedia.org/wiki/IP_multicast因此,您创建了服务器,多播合作伙伴将注册该服务器并从中进行监听 . 为了确保您检测到UDP数据报正在路由中丢弃,每个UD数据报都有其ID号 . 请确保您也可以按发送顺序接收数据报,因此应使用BUFFER或QUEUE,计算正确的顺序 .

    希望有所帮助 .

  • 0

    如果它是像动作游戏这样的客户/服务器游戏,我建议你使用TCP作为用户界面,你不想放弃用户数据,但在游戏中你无法承受快速动作多人游戏中TCP的通信 .

    因为在动作游戏中失去“一些”信息并不是那么糟糕,所以我建议在游戏中使用UDP,或者在任何需要非常快速通信的地方 .

    但如果不是需要快速通信的游戏,我建议您使用TCP .

  • 0

    在我看来,您正在考虑可靠的客户端/服务器通信方法,它将像没有开销TCP / IP通信的广播具有 .

    我也可以使用Messaging . 创建消息驱动器bean(或消息客户端,concumer),它将注册到消息通道或消息队列,并将在PUSH方法上激活 .

    您的消息 生产环境 者创建一条消息,所有其他已注册的客户端服务器(消费者)将被告知它并将异步处理它 . 您可以使用任何平台,也可以使用开源apache MQ . https://en.wikipedia.org/wiki/Message_queue

相关问题