一文读懂 QUIC 协议:更快、更稳、更高效的网络通信

2023-10-26

作者 | 李龙彦 来源:infoQ

你是否也有这样的困扰:打开 APP 巨耗时、刷剧一直在缓冲、追热搜打不开页面、信号稍微差点就直接加载失败……

如果有一个协议能让你的上网速度,在不需要任何修改的情况下就能提升 20%,特别是网络差的环境下能够提升 30% 以上;如果有一个协议可以让你在 WiFi 和蜂窝数据切换时,网络完全不断开、直播不卡顿、视频不缓冲;你愿意去了解一下它吗?它就是 QUIC 协议。本文将从 QUIC 的背景、原理、实践部署等方面来详细介绍。

网络协议栈

1.1 什么叫网络协议?

类似于我们生活中签署的合同一样,比如买卖合同是为了约束买卖双方的行为按照合同的要求履行,网络协议是为了约束网络通信过程中各方(客户端、服务端及中间设备)必须按照协议的规定进行通信,它制定了数据包的格式、数据交互的过程等等,网络中的所有设备都必须严格遵守才可以全网互联。

在网络协议栈中,是有分层的,每一层负责不同的事务。我们讨论最多的有三个:应用层、传输层、网络层。应用层主要是针对应用软件进行约束,比如你访问网站需要按照 HTTP 协议格式和要求进行,你发送电子邮件需要遵守 SMTP 等邮件协议的格式和要求;传输层主要负责数据包在网络中的传输问题,比如如何保证数据传输的时候的安全性和可靠性、数据包丢了怎么处理;网络层,也叫路由转发层,主要负责数据包从出发地到目的地,应该怎样选择路径才能更快的到达。合理的网络协议能够让用户上网更快!

1.2 HTTP/3 协议

HTTP/3 是第三个主要版本的 HTTP 协议。与其前任 HTTP/1.1 和 HTTP/2 不同,在 HTTP/3 中,弃用 TCP 协议,改为使用基于 UDP 协议的 QUIC 协议实现。所以,HTTP/3 的核心在于 QUIC 协议。显然,HTTP/3 属于应用层协议,而它使用的 QUIC 协议属于传输层协议。

1.3 我们需要 HTTP/3 协议吗

很多人可能都会有这样一个疑问,为什么在 2015 年才标准化了 HTTP/2 ,这么快就需要 HTTP/3?

我们知道,HTTP/2 通过引入“流”的概念,实现了多路复用。简单来说,假设你访问某个网站需要请求 10 个资源,你使用 HTTP1.1 协议只能串行地发请求,资源 1 请求成功之后才能发送资源 2 的请求,以此类推,这个过程是非常耗时的。如果想 10 个请求并发,不需要串行等待的话,在 HTTP1.1 中,应用就需要为一个域名同时建立 10 个 TCP 连接才行(一般浏览器不允许建立这么多),这无疑是对资源的极大的浪费。HTTP/2 的多路复用解决了这一问题,能使多条请求并发。

但现实很残酷,为什么很多业务用了 HTTP/2,反倒不如 HTTP1.1 呢?

第一:多流并发带来了请求优先级的问题,因为有的请求客户端(比如浏览器)希望它能尽快返回,有的请求可以晚点返回;又或者有的请求需要依赖别的请求的资源来展示。流的优先级表示了这个请求被处理的优先级,比如客户端请求的关键的 CSS 和 JS 资源是必须高优先级返回的,图片视频等资源可以晚一点响应。流的优先级的设置是一个难以平衡或者难以做到公平合理的事情,如果设置稍微不恰当,就会导致有些请求很慢,这在用户看来,就是用了 HTTP/2 之后,怎么有的请求变慢了。

第二:HTTP/2 解决了 HTTP 协议层面的队头阻塞,但是 TCP 的队头阻塞仍然没有解决,所有的流都在一条 TCP 连接上,如果万一序号小的某个包丢了,那么 TCP 为了保证到达的有序性,必须等这个包到达后才能滑动窗口,即使后面的序号大的包已经到达了也不能被应用程序读取。这就导致了在多条流并发的时候,某条流的某个包丢了,序号在该包后面的其他流的数据都不能被应用程序读取。这种情况下如果换做 HTTP1.1,由于 HTTP1.1 是多条连接,某个连接上的请求丢包了,并不影响其他连接。所以在丢包比较严重的情况下,HTTP/2 整体效果大概率不如 HTTP1.1

事实上,我们并不是真的需要新的 HTTP 版本,而是需要对底层传输控制协议 (TCP) 进行升级。

1.4 QUIC 协议栈

图 0-QUIC 协议栈

QUIC 协议实现在用户态,建立在内核态的 UDP 的基础之上,集成了 TCP 的可靠传输特性,集成了 TLS1.3 协议,保证了用户数据传输的安全。

QUIC 协议的优秀特性

2.1 建连快

数据的发送和接收,要想保证安全和可靠,一定是需要连接的。TCP 需要,QUIC 也同样需要。连接到底是什么?连接是一个通道,是在一个客户端和一个服务端之间的唯一一条可信的通道,主要是为了安全考虑,建立了连接,也就是建立了可信通道,服务器对这个客户端“很放心”,对于服务器来说:你想跟我进行通信,得先让我认识一下你,我得先确认一下你是好人,是有资格跟我通信的。那么这个确认对方身份的过程,就是建立连接的过程。

传统基于 TCP 的 HTTPS 的建连过程为什么如此慢?它需要 TCP 和 TLS 两个建连过程。如图 1 所示(传统 HTTPS 请求流程图):

图 1- 传统 HTTPS 请求流程图

对于一个小请求(用户数据量较小)而言,传输数据只需要 1 个 RTT,但是光建连就花掉了 3 个 RTT,这是非常不划算的,这里建连包括两个过程:TCP 建连需要 1 个 RTT,TLS 建连需要 2 个 RTT。RTT:Round Trip Time,数据包在网络上一个来回的时间。

为什么需要两个过程?可恶就可恶在这个地方,TCP 和 TLS 没办法合并,因为 TCP 是在内核里完成的,TLS 是在用户态。也许有人会说把干掉内核里的 TCP,把 TCP 挪出来放到用户态,然后就可以和 TLS 一起处理了。首先,你干不掉内核里的 TCP,TCP 太古老了,全世界的服务器的 TCP 都固化在内核里了。所以,既然干不掉 TCP,那我不用它了,我再自创一个传输层协议,放到用户态,然后再结合 TLS,这样不就可以把两个建连过程合二为一了吗?是的,这就是 QUIC。

相关视频推荐

10道tcp/ip的问题,让你对网络不再发怵

100行代码实现tcp/ip协议栈,自行准备好Linux系统

C++网络面试题:TCP/UDP应用场景分析,UDP如何实现可靠性设计

免费学习地址:c/c++ linux服务器开发/后台架构师

需要C/C++ Linux服务器架构师学习资料加qun812855908获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

2.1.1 QUIC 的 1-RTT 建连

如图 2 所示,是 QUIC 的连接建立过程:初次建连只需要 1 个 RTT 即可完成建连。后续再次建连就可以使用 0-RTT 特性

图 2-QUIC 建连过程图

QUIC 的 1-RTT 建连:客户端与服务端初次建连(之前从未进行通信过),或者长时间没有通信过(0-RTT 过期了),只能进行 1-RTT 建连。只有先进行一次完整的 1-RTT 建连,后续一段时间内的通信才可以进行 0-RTT 建连。

如图 3 所示:QUIC 的 1-RTT 建连可以分成两个部分。QUIC 连接信息部分和 TLS1.3 握手部分。

图 3-QUIC 建连抓包

QUIC 连接:协商 QUIC 版本号、协商 quic 传输参数、生成连接 ID、确定 Packet Number 等信息,类似于 TCP 的 SYN 报文;保证通信的两端确认过彼此,是对的人。

TLS1.3 握手:标准协议,非对称加密,目的是为了协商出 对称密钥,然后后续传输的数据使用这个对称密钥进行加密和解密,保护数据不被窃取。

我们重点看 QUIC 的 TLS1.3 握手过程。

图 4-QUIC 的 1-RTT 握手流程

我们通过图 4 可以看到,整个握手过程需要 2 次握手(第三次握手是带了数据的),所以整个握手过程只需要 1-RTT(RTT 是指数据包在网络上的一个来回)的时间。

1-RTT 的握手主要包含两个过程:

  1. 客户端发送 Client Hello 给服务端;

  2. 服务端回复 Server Hello 给客户端;

我们通过下图中图 5 和图 6 来看 Client Hello 和 Server Hello 具体都做了啥:

第一次握手(Client Hello 报文)

图 5-Client Hello 报文

首先,Client Hello 在扩展字段里标明了支持的 TLS 版本(Supported Version:TLS1.3)。值得注意的是 Version 字段必须要是 TLS1.2,这是因为 TLS1.2 已经在互联网上存在了 10 年。网络中大量的网络中间设备都十分老旧,这些网络设备会识别中间的 TLS 握手头部,所以 TLS1.3 的出现如果引入了未知的 TLS Version 必然会存在大量的握手失败。

图 6-Client Hello 报文

其次,ClientHello 中包含了非常重要的 key_share 扩展:客户端在发送之前,会自己根据 DHE 算法生成一个公私钥对。发送 Client Hello 报文的时候会把这个公钥发过去,那么这个公钥就存在于 key_share 中,key_share 还包含了客户端所选择的曲线 X25519。总之,key_share 是客户端提前生成好的公钥信息。

最后,Client Hello 里还包括了:客户端支持的算法套、客户端所支持的椭圆曲线以及签名算法、psk 的模式等等,一起发给服务端。

图 7-Client Hello 报文

第二次握手:(Server Hello 报文)

图 8-Server Hello 报文

服务端自己根据 DHE 算法也生成了一个公私钥对,同样的,Key_share 扩展信息中也包含了 服务端的公钥信息。服务端通过 ServerHello 报文将这些信息发送给客户端。

至此为止,双方(客户端服务端)都拿到了对方的公钥信息,然后结合自己的私钥信息,生成 pre-master key,在这里官方的叫法是(client_handshake_traffic_secret 和server_handshake_traffic_secret),然后根据以下算法进行算出 key 和 iv,使用 key 和 iv 对 Server Hello 之后所有的握手消息进行加密。

注意:在握手完成之后,服务端会发送一个 New Session Ticket 报文给客户端,这个包非常重要,这是 0-RTT 实现的基础。

图 9-New Session Ticket 报文

2.1.2 QUIC 的 0-RTT 握手

这个功能类似于 TLS1.2 的会话复用,或者说 0-RTT 是基于会话复用功能的。

图 10- QUIC 的 0-RTT 流程图

通过上面图 10 我们可以看到,client 和 server 在建连时,仍然需要两次握手,仍然需要 1 个 rtt,但是为什么我们说这是 0-rtt 呢,是因为 client 在发送第一个包 client hello 时,就带上了数据(HTTP 请求),从什么时候开始发送数据这个角度上来看,的确是 0-RTT。

我们通过抓包来看 0-RTT 的过程:

图 11- QUIC 的 0-RTT 抓包

所以真正在实现 0-RTT 的时候,请求的数据并不会跟 Initial 报文(内含 Client Hello)一起发送,而是单独一个数据包(0-RTT 包)进行发送,只不过是跟 Initial 包同时进行发送而已。

图 12- QUIC 的 0-RTT 包

我们单独看 Initial 报文发现,除了 pre_share_key、early-data 标识等信息与 1-RTT 时不同,其他并无区别。

2.1.3 QUIC 建连需要注意的问题

第一,QUIC 实现的时候,必须缓存收到的乱序加密帧,这个缓存至少要大于 4096 字节。当然可以选择缓存更多的数据,更大的缓存上限意味着可以交换更大的密钥或证书。终端的缓存区大小不必在整个连接生命周期内保持不变。这里记住:乱序帧一定要缓存下来。如果不缓存,会导致连接失败。如果终端的缓存区不够用了,则其可以通过暂时扩大缓存空间确保握手完成。如果终端不扩大其缓存,则其必须以错误码 CRYPTO_BUFFER_EXCEEDED 关闭连接。

第二,0-RTT 存在前向安全问题,请慎用!

2.2 连接迁移

QUIC 通过连接 ID 实现了连接迁移。

我们经常需要在 WiFi 和 4G 之间进行切换,比如我们在家里时使用 WiFi,出门在路上,切换到 4G 或 5G,到了商场,又连上了商场的 WiFi,到了餐厅,又切换到了餐厅的 WiFi,所以我们的日常生活中需要经常性的切换网络,那每一次的切换网络,都将导致我们的 IP 地址发生变化。

传统的 TCP 协议是以四元组(源 IP 地址、源端口号、目的 ID 地址、目的端口号)来标识一条连接,那么一旦四元组的任何一个元素发生了改变,这条连接就会断掉,那么这条连接中正在传输的数据就会断掉,切换到新的网络后可能需要重新去建立连接,然后重新发送数据。这将会导致用户的网络会“卡”一下。

但是,QUIC 不再以四元组作为唯一标识,QUIC 使用连接 ID 来标识一条连接,无论你的网络如何切换,只要连接 ID 不变,那么这条连接就不会断,这就叫连接迁移!

图 13-QUIC 连接迁移介绍

2.2.1 连接 ID

每条连接拥有一组连接标识符,也就是连接 ID,每个连接 ID 都能标识这条连接。连接 ID 是由一端独立选择的,每个端(客户端和服务端统称为端)选择连接 ID 供对端使用。也就是说,客户端生成的连接 ID 供服务端使用(服务端发送数据时使用客户端生成的连接 ID 作为目的连接 ID),反过来一样的。

连接 ID 的主要功能是确保底层协议(UDP、IP 及更底层的协议栈)发生地址变更(比如 IP 地址变了,或者端口号变了)时不会导致一个 QUIC 连接的数据包被传输到错误的 QUIC 终端(客户端和服务端统称为终端)上。

2.2.2 QUIC 的连接迁移过程

QUIC 限制连接迁移为仅客户端可以发起,客户端负责发起所有迁移。如果客户端接收到了一个未知的服务器发来的数据包,那么客户端必须丢弃这些数据包。

如图 14 所示,连接迁移过程总共需要四个步骤。

  1. 连接迁移之前,客户端使用 IP1 和服务端进行通信;

  2. 客户端 IP 变成 IP2,并且使用 IP2 发送非探测帧给服务端;

  3. 启动路径验证(双方都需要互相验证),通过 PATH_CHANLLENGE 帧和 PATH_RESPONSE 帧进行验证。

  4. 验证通过后,使用 IP2 进行通信。

图 14- 连接迁移流程图

2.3 解决 TCP 队头阻塞问题

在 HTTP/2 中引入了流的概念。目的是实现 多个请求在同一个连接上并发,从而提升网页加载的效率。

图 15-QUIC 解决 TCP 队头阻塞问题

由图 15 来看,假设有两个请求同时发送,红色的是请求 1,蓝色的是请求 2,这两个请求在两条不同的流中进行传输。假设在传输过程中,请求 1 的某个数据包丢了,如果是 TCP,即使请求 2 的所有数据包都收到了,但是也只能阻塞在内核缓冲区中,无法交给应用层。但是 QUIC 就不一样了,请求 1 的数据包丢了只会阻塞请求 1,请求 2 不会受到阻塞。

有些人不禁发问,不是说 HTTP2 也有流的概念吗,为什么只有 QUIC 才能解决呢,这个根本原因就在于,HTTP2 的传输层用的 TCP,TCP 的实现是在内核态的,而流是实现在用户态度,TCP 是看不到“流”的,所以在 TCP 中,它不知道这个数据包是请求 1 还是请求 2 的,只会根据 seq number 来判断包的先后顺序。

2.4 更优的拥塞控制算法

拥塞控制算法中最重要的一个参数是 RTT,RTT 的准确性决定了拥塞控制算法的准确性;然而,TCP 的 RTT 测量往往不准确,QUIC 的 RTT 测量是准确的。

图 16-TCP 计算 RTT

如图 16 所示:由于网络中经常出现丢包,需要重传,在 TCP 协议中,初始包和重传包的序号是一样的,拥塞控制算法进行计算 RTT 的时候,无法区别是初始包还是重传包,这将导致 RTT 的计算值要么偏大,要么偏小。

图 17-QUIC 计算 RTT

如图 17 所示:QUIC 通过 Packet Number 来标识包的序号,而且规定 Packet Number 只能单调递增,这也就解决了初始包和重传包的二义性。从而保证 RTT 的值是准确的。

另外,不同于 TCP,QUIC 的拥塞控制算法是可插拔的,由于其实现在用户态,服务可以根据不同的业务,甚至不同的连接灵活选择使用不同的拥塞控制算法。(Reno、New Reno、Cubic、BBR 等算法都有自己适合的场景)

2.5 QUIC 的两级流量控制

很多人搞不清楚流量控制与拥塞控制的区别。二者有本质上的区别。

流量控制要解决的问题是:接收方控制发送方的数据发送的速度,就是我的接收能力就那么大点,你别发太快了,你发太快了我承受不住,会给你丢掉 你还得重新发。

拥塞控制要解决的问题是:数据在网络的传输过程中,是否网络有拥塞,是否有丢包,是否有乱序等问题。如果中间传输的时候网络特别卡,数据包丢在中间了,发送方就需要重传,那么怎么判断是否拥塞了,重传要怎么重传法,按照什么算法进行发送数据才能尽可能避免数据包在中间路径丢掉,这是拥塞控制的核心。

所以,流量控制解决的是接收方的接收能力问题,一般采用滑动窗口算法;拥塞控制要解决的是中间传输的时候网络是否拥堵的问题,一般采用慢启动、拥塞避免、拥塞恢复、快速重传等算法。

图 18-QUIC 流量控制

QUIC 是双级流控,不仅有连接这一个级别的流控,还有流这个级别的流控。如下图所示,每个流都有自己的可用窗口,可用窗口的大小取决于最大窗口数减去发送出去的最大偏移数,跟中间已经发送出去的数据包,是否按顺序收到了对端的 ACK 无关。

QUIC 协议如何优化

QUIC 协议定义了很多优秀的功能,但是在实现的过程中,我们会遇到很多问题导致无法达到预期的性能,比如 0-RTT 率很低,连接迁移失败率很高等等。

3.1 QUIC 的 0-RTT 成功率不高

导致 0-RTT 成功率不高的原因一般有如下几个:

1. 服务端一般都是集群,对于客户端来说,处理请求的服务端是不固定的,新的请求到来时,如果当前 client 没有请求过该服务器,则服务器上没有相关会话信息,会把该请求当做一个新的连接来处理,重新走 1-RTT。

针对此种情况,我们可以考虑集群中所有的服务器使用相同的 ticket 文件。

2. 客户端 IP 不是固定的,在发生连接迁移时,服务端下发的 token 融合了客户端的 IP,这个 IP 变化了的话,携带 token 服务端校验不过,0-RTT 会失败。

针对这个问题,我们可以考虑采用如图 19 所示的方法,使用设备信息或者 APP 信息来生成 token,唯一标识一个客户端。

图 19- 使用设备信息提高 0-RTT 的成功率

3. Session Ticket 过期时间默认是 2 天,超过 2 天后就会导致 0-RTT 失败,然后降级走 1-RTT。可以考虑增长过期时间。

3.2 实现连接迁移并不容易。

连接迁移的实现,不可避开的两个问题:一个是四层负载均衡器对连接迁移的影响,一个是七层负载均衡器对连接迁移的影响。

四层负载均衡器的影响:LVS、DPVS 等四层负载均衡工具基于四元组进行转发,当连接迁移发生时,四元组会发生变化,该组件就会把同一个请求的数据包发送到不同的后端服务器上,导致连接迁移失败;

七层负载均衡器的影响(QUIC 服务器多核的影响):由于多核的影响,一般服务器会有多个 QUIC 服务端进程,每个进程负载处理不同的连接。内核收到数据包后,会根据二元组(源 IP、源 port)选择已经存在的连接,并把数据包交给对应的 socket。在连接迁移发生时,源地址发生改变,可能会让接下来的数据包去到不同的进程,影响 socket 数据的接收。

如何解决以上两个问题?DPVS 要想支持 QUIC 的连接迁移,就不能再以四元组进行转发,需要以连接 ID 进行转发,需要建立 连接 ID 与对应的后端服务器的对应关系;

QUIC 服务器也是一样的,内核就不能用四元组来进行查找 socket,四元组查找不到时,就必须使用连接 ID 进行查找 socket。但是内核代码又不能去修改(不可能去更新所有服务器的内核版本),那么我们可以使用 eBPF 的方法进行解决。如下图 20 所示:

图 20- 多核 QUIC 服务器解决连接迁移问题

3.3 UDP 被限速或禁闭

业内统计数据全球有 7% 地区的运营商对 UDP 有限速或者禁闭,除了运营商还有很多企业、公共场合也会限制 UDP 流量甚至禁用 UDP。这对使用 UDP 来承载 QUIC 协议的场景会带来致命的伤害。对此,我们可以采用多路竞速的方式使用 TCP 和 QUIC 同时建连。除了在建连进行竞速以外,还可以对网络 QUIC 和 TCP 的传输延时进行实时监控和对比,如果有链路对 UDP 进行了限速,可以动态从 QUIC 切换到 TCP。

图 21-QUIC 和 TCP 协议竞速

3.4 QUIC 对 CPU 消耗大

相对于 TCP,为什么 QUIC 更消耗资源?

  1. QUIC 在用户态实现,需要更多的内核空间与用户空间的数据拷贝和上下文切换;

  2. QUIC 的 ACK 报文也是加密的,TCP 是明文的。

  3. 内核知道 TCP 连接的状态,不用为每一个数据包去做诸如查找目的路由、防火墙规则等操作,只需要在 tcp 连接建立的时候做一次即可,然而 QUIC 不行;

总的来说,QUIC 服务端消耗 CPU 的地方主要有三个:密码算法的开销;udp 收发包的开销;协议栈的开销;

针对这些,我们可以适当采取优化措施来:

  1. 使用 Intel 硬件加速卡卸载 TLS 握手

  2. 开启 GSO 功能。

  3. 数据在传输过程中,可以将一轮中所有的 ACK 解析后再同时进行处理,避免处理大量的 ACK。

  4. 适当将 QUIC 的包长限制调高(比如从默认的 1200 调到 1400 个字节)

  5. 减少协议栈的内存拷贝

QUIC 的性能

从公开的数据来看,国内各个厂(腾讯、阿里、字节、华为、OPPO、网易等等)使用了 QUIC 协议后,都有很大的提升,比如网易上了 QUIC 后,响应速度提升 45%,请求错误率降低 50%;比如字节火山引擎使用 QUIC 后,建连耗时降低 20%~30%;比如腾讯使用 QUIC 后,在腾讯会议、直播、游戏等场景耗时也降低 30%;

图 22- 字节火山引擎 QUIC 业务收益

总 结

QUIC 协议的出现,为 HTTP/3 奠定了基础。这是近些年在 web 协议上最大的变革,也是最优秀的一次实践。面对新的协议,我们总是有着各种各样的担忧,诚然,QUIC 协议在稳定性上在成熟度上,的确还不如 TCP 协议,但是经过近几年的发展,成熟度已经相当不错了,Nginx 近期也发布了 1.25.0 版本,支持了 QUIC 协议。所以面对这样优秀的协议,我们希望更多的公司,更多的业务参与进来使用 QUIC,推动 QUIC 更好的发展,推动用户上网速度更快!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一文读懂 QUIC 协议:更快、更稳、更高效的网络通信 的相关文章

  • 定时器 C#.开始、停止和获取调用之间的时间量[重复]

    这个问题在这里已经有答案了 可能的重复 如何测量函数运行了多长时间 https stackoverflow com questions 10107140 how to measure how long is a function runni
  • .NET 可移植类库和 UDP 支持

    我正在为 Philips Hue Lights 编写一个 C 库 我正在尝试在 NET 可移植集中编写基本 API 包装器 这样我就可以在 Windows 8 RT WP 等各种平台上重复使用该库 API 本身完全通过 HTTP 使用 RE
  • 发送大量UDP数据包时如何减少系统调用开销? (Windows 和 Linux)

    例如 我在 Windows 上发送 100000 个 UDP 数据包 对于每个数据包 我需要调用WSASendTo 一次 所以可能会引入很多系统调用开销 有没有办法进行批量发送并减少这种开销 我在谷歌搜索了一段时间后找不到适用于 Windo
  • python udp客户端超时机制

    如果服务器套接字中生成的兰特数小于4 我的客户端套接字将暂停接收数据 我需要设置超时机制以允许客户端套接字检测到 超时 然后继续发送消息 在我运行服务器套接字然后运行客户端套接字后 出现以下错误消息 Traceback most recen
  • 如何用C语言创建UDP服务器?

    我正在尝试用 C 语言 在 Linux 下 编写一个 UDP 服务器 我知道在socket 我必须使用的功能SOCK DGRAM并不是SOCK STREAM if list s socket AF INET SOCK DGRAM IPPRO
  • 在 Android 上显示实时 UDP 或 RTP 流(组播)

    我刚接触 Android 开发几周 我需要编写一个应用程序 可以向用户显示以 UDP 或 RDP 多播的实时流 该流位于诸如 rtp 230 0 0 11 1234 之类的地址 并通过该模块通过 WIFI 发出 我已经尝试从播放器 Daro
  • 从 iOS 应用程序上的 UDP 服务器接收数据无法在 Linux 服务器上工作,但可以在 macbook pro 上工作 [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 背景 我做
  • UDP 数据报中发送的消息未经过净化?

    我的代码如下 一切都按照我想要的方式进行 但是当我的消息收到时 它们的末尾有很多框 有点像这样 消息 你好 如何才能让接收和打印的内容仅为 Message hello 我非常感谢任何帮助 import java io import java
  • 使用 Winsock 通过单个 UDP 服务器处理 10 个客户端

    我已经使用 UDP 套接字建立了一个服务器 客户端应用程序 但我的服务器无法一次处理多个客户端 现在我想修改我的应用程序 让 10 个客户端分别运行在不同的计算机上 而我的服务器运行在单独的计算机上 我希望我的服务器能够与 10 个不同机器
  • UDP 数据包在交付时是否保证是完整的、具有实际意义的?

    众所周知 UDP 用户数据报协议 并不安全 因为用它发送的数据包的顺序可能不按顺序传送 甚至根本不按顺序传送 但是 如果发送了 UDP 数据包 该数据包中的信息在实际意义上 99 99 及以上 是否保证正确 在实际意义上 99 99 及以上
  • Android 无法通过互联网从 PC 服务器接收 UDP 数据

    我目前正在探索用Java 进行UDP 数据包传输 以在Android 上创建多人游戏 我使用通常的 127 0 0 1 成功地在 Nexus 4 内交换数据包 并且还成功地在本地网络中的 PC 服务器和 Android 客户端之间交换数据包
  • UDP 服务器套接字缓冲区溢出

    我正在 Linux 上编写 C 应用程序 我的应用程序有一个 UDP 服务器 它在某些事件上向客户端发送数据 UDP 服务器还接收来自客户端的一些反馈 确认 为了实现这个应用程序 我使用了一个 UDP 套接字 例如int fdSocket
  • 为什么UDP服务器上的UDP客户端端口会改变

    我一直在关注一个简 单的 UDP 服务器 客户端教程 发现here http www binarytides com udp socket programming in winsock 我有一个关于客户端连接到服务器的端口的快速问题 仅从代
  • 接收来自 N 个客户端的响应,以回复通过 UDP 的广播请求

    我正在为特定类型的网络多媒体设备实现一种 IP 查找器 我想找出 LAN 中该类型的所有活动设备及其 IP 地址和其他详细信息 设备有自己的设备发现方式 其工作原理如下 客户端通过 UDP 通过 LAN 发送广播请求 目的端口号是固定的 作
  • Go:如何接收整个 UDP 数据报

    我的问题 使用 net Read 方法仅复制给定字节数组或切片大小的字节数 当然 我不想每次都分配最大 64 kB 的 UDP 数据报 有没有go如何确定数据报的大小 位于数据报头中 或再次读取直到数据报完全读取 Try 从UDP读取 ht
  • C#/Unity - 无法从异步方法调用 Unity 方法

    我正在使用Unity3D 这是我的异步方法 private void Receive IAsyncResult ar try IPEndPoint ipEndPoint null byte data udpClient EndReceive
  • VS2015:应用程序无法正确启动(0xc000007b)

    我在 Visual Studio 2015 上为 Windows 10 PC 编写了代码 该应用程序主要关注 UDP 通信 我使用 boost 库 它工作正常 但当我将代码文件夹移至 Windows 7 时 我收到错误 应用程序无法正确启动
  • 互联网上的 UDP 多播?

    我不确定如何最好地解决我的问题 我有一个在远程计算机上运行的服务 用于接收和处理 UDP 数据包 我希望该服务能够将这些数据包重新发送给任何需要它们的人 可能是任何人 通常是一台机器 但也可能更多 我认为 UDP 多播将是理想的 该服务可以
  • 为什么通过UdpClient发送会导致后续接收失败?

    我正在尝试创建一个 UDP 服务器 它可以向所有向其发送消息的客户端发送消息 真实情况要复杂一些 但最简单的方法是将其想象为一个聊天服务器 之前发送过消息的每个人都会收到其他客户端发送的所有消息 所有这一切都是通过UdpClient 在单独
  • 您可以bind()和connect() UDP连接的两端吗

    我正在编写一个点对点消息队列系统 它必须能够通过 UDP 运行 我可以任意选择一侧或另一侧作为 服务器 但这似乎不太正确 因为两端都从另一端发送和接收相同类型的数据 是否可以绑定 和连接 两端 以便它们只能彼此发送 接收 这似乎是一种非常对

随机推荐

  • 【Android】线性布局(LinearLayout)最全解析

    Android 线性布局 LinearLayout 最全解析 一 LinearLayout概述 二 LinearLayout常用属性 2 1 orientation属性 2 2 gravity属性 2 3 layout weight属性 一
  • STM32H7串口查询方式接收串口接收溢出导致死机问题

    串口溢出后 因为接收移位寄存器不会把接收到的数据放到接收寄存器中 则RXNE RXFNE不会再置位 不能再接收 表现为串口死机 STATIC INLINE uint32 t LL USART IsActiveFlag RXNE RXFNE
  • STM32F407单片机移植MS5611气压计(基于IIC)---同时解决温度低于20度时计算得到的大气压错误的问题

    最近一个工程项目需要使用MS5611气压计 就花时间研究了一下 发现网上很多都是基于STM32F103单片机的MS5611气压计源程序 当移植到STM32F407时发现采集的大气压力和温度值不对 同时发现网上部分程序在温度高于20度时 计算
  • 11月编程语言排行出了!榜单有何新变化?

    11月TIOBE编程排行榜已更新 一起看看本月各大编程语言有何新进展 11月TIOBE编程排行榜前15名 TOP 10编程语言TIOBE指数走势 素材来自https www tiobe com tiobe index 如侵删 在本月TIOB
  • 数据库知识整理 - 数据库恢复技术(故障种类、数据转储、日志文件、恢复策略)

    主要内容 事务的基本概念 故障的种类 1 事务内部的故障 2 系统故障 3 介质故障 4 计算机病毒 数据库恢复技术 数据转储 登记日志文件 登记日志文件的作用以及原则 恢复策略 事务故障的恢复 系统故障的恢复 介质故障的恢复
  • 如何将CAD绘图软件的语言设置为中文状态下

    我们在进行使用CAD绘图软件来绘制图纸的时候 一般都需要建CAD编辑器进行设置一下在使用 那么 如何将CAD绘图软件的语言设置为中文状态下 具体要怎么来进行操作呢 那下面小编就来教教大家将CAD绘图软件设置为中文状态下的操作方法吧 希望对你
  • 关于struts2和javamail的配合使用

    这几天用到了javamail 开始写了个程序 建了个java项目 可以正常运行 但是后来加入到struts2项目中 就开始报错ClassNotFound之类的错误 解决方法是在myeclipse的安装目录下找到common文件夹 打开其中的
  • Arduino pro micro开发板的程序烧录问题

    Arduino pro micro是我大二的时候买的一个开发板 当时是玩Arduino开发板之后 尝试做一个小东西 但是买回来后 不知道程序怎么下载 多种尝试也没有成功 时隔多年 在家收拾东西翻出来后 再试了一下 发现我当时想多了 没好好地
  • IDEA教程之Activiti插件

    本文作者 Spring ZYL 文章来源 人生就是一个不断学习的过程 码农StayUp CSDN博客 SpringBoot全家桶 Java数据结构与算法分析 设计模式领域博主 版权声明 本文版权归作者所有 转载请注明出处 一 安装Activ
  • 《软件测试》第十四章 网站测试

    软件测试 第十四章 网站测试 14 0 前言 14 1 网页基础 14 2 黑盒测试 14 2 1 文本 14 2 2 超级链接 14 2 3 图片 14 2 4 表单 14 2 5 对象和其他各种简单的功能 14 3 灰盒测试 14 4
  • QQ和MSN 在线代码

    QQ在线聊天代码 a href img src images qq交谈 bmp alt qq交谈 width 68 height 29 border 0 a MSN在线聊天代码 a href target blank img src ima
  • Callable 和 Future

    Callable 和 Future 是 Java 并发编程中用于处理多线程任务的两个关键接口 它们通常与线程池一起使用 以实现异步任务执行和获取结果的功能 Callable Callable 是一个泛型接口 它定义了一个带有返回值的任务 与
  • 多线程爬虫的实现----threading库的使用

    1 作爬虫的时候为了提升抓取的速度 这个时候就需要开启多个线程同时抓取数据 今天就分享一下如何使用Python中的threading库实现多线程抓取数据 from shop import ShopSpider import threadin
  • 微服务框架相关 OpenFeign 源码

    目录 一 基础 二 初始化注册 三 FeignClient 自动配置 四 FeignClient 创建 五 网络请求的发出 六 负载均衡 SpringCloud Loadbalancer 一 基础 使用 OpenFeign 流程 项目中引入
  • 2如何识别操作系统_信创产业成为风口,如何“迁移”值得研究(二)

    在上一讲 信创产业成为风口 如何 迁移 值得研究 中 我们分析了什么是 信创 以及数据迁移在信创过程中的重要意义及其基本要求 本次文章中我们将继续分析 信创实践过程中数据迁移的难点及其解决之道 1难点1 迁移场景复杂 在信创实践过程中 随着
  • html搜索栏热搜效果,CSS3实战开发:百度新闻热搜词特效实战开发_html/css_WEB-ITnose...

    各位网友 今天这篇文章 我将手把手带领大家开发百度新闻首页的 新闻热搜词 特效 在这个特效中应用的知识点都很基础 如果你对这些还不清楚 可以关注我以前写的详细教程 今天讲这个案例 也是希望告诉大家 在开发一个特效的时候 请不要将问题复杂化
  • valn的基础配置

    vlan作业 1 交换机进行vlan配置 lsw1 lsw2 2 进行单臂路由的配置 3 DHCP配置 地址池的配置 端口启动
  • LR-ASPP论文

    论文地址 https arxiv org abs 1905 02244 摘要 我们提出了基于互补搜索技术的组合以及一个新颖的架构设计的下一代移动网络 MobileNetV3通过结合NetAdapt算法补充的硬件网络架构搜索 NAS 调整到移
  • 配置JAVA环境变量

    一 自行安装JDK 位置默认C盘 JDK全称是Java Development Kit 是整个Java的核心 包括了Java运行环境 Java工具和Java基础类库 JDK 是整个Java的核心 包括了Java运行环境 Java工具和Jav
  • 一文读懂 QUIC 协议:更快、更稳、更高效的网络通信

    作者 李龙彦 来源 infoQ 你是否也有这样的困扰 打开 APP 巨耗时 刷剧一直在缓冲 追热搜打不开页面 信号稍微差点就直接加载失败 如果有一个协议能让你的上网速度 在不需要任何修改的情况下就能提升 20 特别是网络差的环境下能够提升