初识TCP & UDP
TCP
一、TCP特点
面向连接的协议,在传输数据前需要建立一条可靠连接
流式协议,TCP将数据看作字节流。传输过程中数据是可以被分割为多个数据包在接收端重新组装的。
TCP通过校验和\序列号和确认应答来确保数据的可靠传输,出错回重新传输。
服务器被动连接,客户端主动连接。
二、TCP编程
server端
1.创建套接字socket()
1 |
|
2.绑定套接字bind()
1 | #include <sys/types.h> |
3.监听套接字listen()
1 |
|
4.接收连接accept()
1 |
|
5.通信recv()/send()
1 |
|
1 |
|
6.关闭套接字()
client端
1.socket()
2.connect()
1 |
|
3.send()/recv()
4.close()
三、OSI模型
| 应用层 | HTTP、SMTP、SNMP、FTP、Telnet、SIP、SSH、NFS、RTSP、XMPP、Whois、ENRP、等等 |
|---|---|
| 表示层 | XDR、ASN.1、SMB、AFP、NCP、等等 |
| 会话层 | ASAP、SSH、RPC、NetBIOS、ASP、Winsock、BSD Sockets、等等 |
| 传输层 | TCP、UDP、TLS、RTP、SCTP、SPX、ATP、IL、等等 |
| 网络层 | IP、ICMP、IGMP、IPX、BGP、OSPF、RIP、IGRP、EIGRP、ARP、RARP、X.25、等等 |
| 数据链路层 | 以太网、令牌环、HDLC、帧中继、ISDN、ATM、IEEE 802.11、FDDI、PPP、等等 |
| 物理层 | 例如铜缆、网线、光缆、无线电等等 |
UDP
DTLS
基础部分
DTLS (Datagram Transport Layer Security) 基于 UDP 场景下数据包可能丢失或重新排序的现实情况下,为 UDP 定制和改进的 TLS 协议。
DTLS 的本质就是:试图在一个不可靠的传输通道(UDP)上,建立一个安全的加密连接(TLS)。
在 WebRTC 中使用 DTLS 的地方包括两部分:协商和管理 SRTP 密钥和为 DataChannel 提供加密通道。
1 | +-----------------------+ |
UDP(User Datagram Protocol(用户数据报协议)):网络传输层的一个协议。
- 无连接 (Connectionless): 发送数据前不需要建立连接(没有“握手”过程)。
- 不可靠 (Unreliable): 它不保证数据包一定能送到。如果半路丢了,UDP 协议层本身不会重发(除非应用层自己写逻辑去补救)。
- 无序 (Unordered): 先发的数据包不一定先到。
- 低延迟 (Low Latency): 因为它省去了建立连接、确认收到、重传丢失包等复杂的步骤,所以它的速度非常快,开销很小。
为什么 WebRTC 要用 UDP?
在实时音视频通话(WebRTC 的核心场景)中,实时性比完整性更重要。DTLS :
- 继承了 TLS 的安全性: 依然提供加密、身份认证和完整性校验。
- 适应了 UDP 的不可靠:
- 它在 TLS 协议中显式增加了序列号(Sequence Number),自己来处理重排序问题。
- 它增加了重传机制,如果在握手阶段包丢了,DTLS 会自己负责重传,而不是依赖底层协议。
DTLS 的握手过程比 TLS 多了一个HelloVerifyRequest(为了防止 DoS 攻击)
DTLS 的握手流程
TLS 握手 (标准 TCP 场景)
在 TCP 已经建立连接(三次握手完成)之后,TLS 握手开始。它的核心目标是:交换随机数 -> 协商算法 -> 生成密钥 -> 验证密钥。
1 | Client Server |
关键步骤详解:
1、 Client Hello: 客户端打招呼。
- “我有这些加密算法(Cipher Suites),这是我的随机数 $Random_C$。”
2、Server Hello & Certificate: 服务端回应。
- “我选这个算法,这是我的随机数 $Random_S$,这是我的证书(公钥在里面)。”
3、Key Exchange (密钥交换): 这是最关键的一步。客户端生成一个预主密钥 (Pre-Master Secret),用服务器的公钥加密发过去。
- 此时,双方都有了三个要素:$Random_C$, $Random_S$, Pre-Master Secret。
- 双方利用这三个要素,通过同样的算法算出最终的 Master Secret (会话密钥)。
4、ChangeCipherSpec: 信号,表示“从这条消息以后,我发的都是密文”。
5、Finished: 双方互相发一条加密的消息(包含之前所有握手消息的 Hash)。如果对方能解密并校验 Hash 成功,说明双方密钥一致,握手成功。
DTLS 握手流程 (UDP 场景)
DTLS 基于 TLS,但 UDP 是不可靠的(没连接、易丢包、易被伪造)。
为了解决这些问题,DTLS 在流程中增加了两个核心机制:
- Cookie 验证 (防 DoS 攻击): UDP 很容易伪造源 IP。为了防止攻击者伪造大量 IP 向服务器发送
ClientHello消耗服务器资源,DTLS 要求客户端先“验证身份”。 - 重传与消息分片 (Flight 机制): 把几条消息打包成一个Flight。如果这个组里缺了包,就超时重传。
1 | Client Server |
第一阶段:防 DoS 验证(Cookie Exchange)
- Step 1: 客户端发送
ClientHello。 - Step 2 (关键区别): 服务端不立即分配资源,而是计算一个无状态的 Cookie,通过
HelloVerifyRequest发回给客户端。意思是:“如果你是真的客户端,就把这个 Cookie 放在下个包里带回来。”- 目的: 确认发包的 IP 是真实存在的,不是伪造的攻击源。
- Step 3: 客户端收到 Cookie,再次发送
ClientHello(这次带上了 Cookie)。服务端验证通过后,才正式开始 TLS 握手。
第二阶段:正式握手(带重传机制)
- 接下来的步骤(Step 4, 5, 6)和 TLS 几乎一样。
- 区别在于“Flight(飞行组)”:
- 比如 Step 4 中的四条消息(ServerHello 到 ServerHelloDone)被视为 Flight 4。
- UDP 可能会丢掉其中的
Certificate包。 - 如果客户端长时间没收到完整的 Flight 4,它不会回复。
- 服务端超时后,会重传整个 Flight 4,而不是只重传丢失的那一个包。
| 字段 | 作用 | 解决 UDP 的问题 |
|---|---|---|
| Epoch (纪元) | 标记当前是否处于加密状态(握手前是0,握手后是1)。 | 处理加密/未加密状态切换的模糊性。 |
| Sequence Number (序列号) | 每个记录都有显式的序列号(TLS 是隐式的)。 | 解决乱序 (Reordering) 和 丢包 (Loss)。接收方根据序号重排。 |
| Cookie | 握手第一步的令牌。 | 解决 DoS 攻击。防止伪造源 IP 耗尽服务器内存。 |
| Fragment (分片) | 允许把一个大的 TLS 握手包拆成多个小的 UDP 包。 | 解决 MTU 限制。TLS 证书可能很大,超过 UDP 单包限制,必须拆分。 |
握手方式
基于证书 (Certificate-based)
- 工作原理:
- 双方交换证书(Certificate)。
- 利用非对称加密算法(如 RSA 或 ECDSA)来验证身份并交换密钥。
在 WebRTC 中的特殊性(重点):
- WebRTC 通常不使用权威机构(CA)签发的证书。
- WebRTC 使用的是自签名证书 (Self-signed Certificate)。
怎么验证真伪? 依靠信令通道(SDP)交换的 指纹 (Fingerprint)。
流程: 浏览器 A 在 SDP 里告诉浏览器 B:“我等会儿会给你发个证书,它的哈希值是 SHA-256: XX:YY:ZZ…”。等 DTLS 握手时,B 收到证书,算出哈希值一对比,对上了就是真的。
- 优点: 灵活,不需要双方提前预设密码,适合 P2P 这种陌生人之间的连接。
- 缺点: 计算量大(非对称加密消耗 CPU),握手包比较大(证书占流量,可能导致 UDP 分片)。
PSK (Pre-Shared Key)
- 工作原理:
- 不需要证书。
- 双方提前在本地配置好同一个密钥(Key)和 ID(Identity)。
- 握手时,直接告诉对方:“我是 ID: client1,我知道那个秘密”。
- 典型套件长这样:
TLS_PSK_WITH_AES_128_GCM_SHA256 - 在 WebRTC 中的地位:
- 标准浏览器(Chrome/Safari):通常不支持或不开放 PSK 模式给开发者。浏览器主要只跑基于证书的模式。
- 嵌入式/服务器端 WebRTC (如 GStreamer, Janus, IoT 设备):为了省电或省 CPU,可能会魔改使用 PSK。
- 优点:
- 极快: 少了繁重的证书验证和公钥运算。
- 极小: 握手包非常小,非常适合带宽受限的弱网环境。
- 缺点: 扩展性差。需要给每个设备预埋密钥。
区别手段:Server Hello 中的 Cipher Suite
在抓包看到 Server Hello 数据包选中的 Cipher Suite:
- 看到 ECDHE-RSA / ECDHE-ECDSA 字样:
- 例如:
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - 结论: 基于证书(WebRTC 默认就是这种)。
- 例如:
- 看到 PSK 字样:
- 例如:
TLS_PSK_WITH_AES_128_CBC_SHA - 结论: PSK 握手。
- 例如:




