
一个套接字由:ip地址和port决定。
TOS
**IP 数据包的服务类型(Type of Service,TOS)**是 IPv4 头部中的一个字段,用来告诉网络设备(如路由器)该数据包希望获得怎样的传输服务。
1. TOS 字段的定义(IPv4)
最初的 TOS 字段包含 8 位,含义如下:
| 位段 | 名称 | 作用 |
|---|---|---|
| 0--2 | 优先级(Precedence) | 已废弃,用于指定包的重要程度 |
| 3 | 最小延迟(Low Delay) | 希望获得更低时延 |
| 4 | 最大吞吐量(High Throughput) | 希望更多带宽 |
| 5 | 最高可靠性(High Reliability) | 希望更高传输可靠性 |
| 6 | 最低成本(Low Cost) | 希望选择更便宜的链路 |
| 7 | 保留 | 未使用 |
后来 TOS 被替代为两个新的概念:
- DSCP(Differentiated Services Code Point)区分服务编码,占前 6 位
- ECN(Explicit Congestion Notification)显式拥塞通知,占后 2 位
2. TOS/DSCP 的作用
简而言之:告诉网络"我是什么类型的流量,你应该怎么处理我"。
主要作用包括:
① 流量分类与优先级控制
路由器和交换机根据 DSCP 对流量进行分类、队列管理,实现 QoS。
例如:
- 语音(VoIP)→ 低延迟
- 视频流 → 低延迟 + 高吞吐
- 文件下载 → 高吞吐
- 普通网页 → 默认处理
② 控制带宽、延迟、丢包率
不同类型的业务可放入不同的队列,实现:
- 延迟敏感流量的加速转发
- 低优先级流量在拥塞时丢弃
③ 实现服务质量(QoS)策略
运营商、企业网络常使用 DSCP 来:
- 限制或优先某些流量(如语音、视频、VPN)
- 在 MPLS、SD-WAN 等网络中保持端到端 QoS
④ 支持拥塞控制(通过 ECN)
ECN 可以在网络发生拥塞时通知发送方减速,而无需丢包。
3. 举例
例如 VoIP 电话包可能设置:
DSCP = EF (Expedited Forwarding = 46)
路由器看到 EF 就知道:
- 要求低延迟
- 要求低抖动
- 尽量不丢
用于语音质量保障。
总结
IP 服务类型(TOS/DSCP/ECN)的作用:
- 为数据包标记期望的服务质量(QoS)
- 帮助网络设备分类流量
- 实现不同优先级的带宽、延迟、丢包控制
- 支持拥塞通知(ECN)
它是现代网络实现 QoS 的核心机制之一。
Socket选项
1. SOL_SOCKET(通用 Socket 层)选项
这些对所有协议都适用(TCP、UDP、UNIX socket 等)。
| 选项 | 名称 | 作用 |
|---|---|---|
| SO_REUSEADDR | 端口快速复用 | 允许在 TIME_WAIT 状态重新绑定端口;允许不同 IP 绑定同端口 |
| SO_REUSEPORT | 端口共享 | 多进程/线程绑定同一 IP+端口,内核分发连接(高并发关键) |
| SO_KEEPALIVE | TCP keep-alive | 定期发送探测包判断对端是否仍在线;防止死连接 |
| SO_LINGER | 延迟关闭 | 控制 socket close() 行为:立刻 RST、等待发送数据、或正常关闭 |
| SO_SNDBUF | 发送缓冲区大小 | 设置发送缓冲区(内核发送队列)大小 |
| SO_RCVBUF | 接收缓冲区大小 | 设置接收缓冲区大小(内核接收队列) |
| SO_BROADCAST | 广播 | 允许 UDP 发送广播包(255.255.255.255) |
| SO_ERROR | 错误队列 | 查询 socket 最近的错误 |
| SO_TYPE | socket 类型 | 返回 socket 是 STREAM、DGRAM 等 |
| SO_OOBINLINE | 内联带外数据 | TCP OOB 数据放入正常流而不是单独通道 |
| SO_RCVTIMEO | 接收超时 | recv() 超时时间 |
| SO_SNDTIMEO | 发送超时 | send() 超时时间 |
| SO_DONTROUTE | 不走路由 | 不使用路由表(仅发本地网络) |
| SO_MARK(Linux) | fwmark | 给 socket 打标,用于 iptables / 路由策略 |
2. TCP 层选项(IPPROTO_TCP)
| 选项 | 名称 | 作用 |
|---|---|---|
| TCP_NODELAY | 禁用 Nagle | 关闭 Nagle 算法,降低小包延迟(用于请求-响应、RPC) |
| TCP_KEEPIDLE | keepalive 启动时间 | TCP keep-alive 空闲多久后开始发送探测包 |
| TCP_KEEPINTVL | keepalive 间隔 | 两次 keepalive 探测包间隔 |
| TCP_KEEPCNT | keepalive 失败次数 | 探测多少次失败后认为连接断开 |
| TCP_SYNCNT | SYN 重试次数 | TCP 三次握手 SYN 重传次数 |
| TCP_MAXSEG | 最大段大小 | 设置 TCP MSS |
| TCP_QUICKACK | 快速 ACK | 更快发送 ACK(减少延迟) |
| TCP_CORK | 数据聚合 | 等待更多数据后再发包(与 NODELAY 相反)---优化大块传输 |
| TCP_DEFER_ACCEPT | 延迟 accept | LISTEN socket 直到有数据才返回 accept() |
| TCP_FASTOPEN | 快速打开 | TCP 0-RTT,减少握手延迟 |
| TCP_USER_TIMEOUT | 用户超时 | 发送失败多久后放弃重传 |
3. IP 层选项(IPv4,IPPROTO_IP)
| 选项 | 名称 | 作用 |
|---|---|---|
| IP_TOS | 服务类型(TOS/DSCP) | 设置 IP 头部 TOS 字段,用于 QoS(低延迟/高吞吐/DSCP) |
| IP_TTL | 生存时间 | 设置 IP TTL(跳数) |
| IP_MTU_DISCOVER | MTU 发现 | 控制 PMTUD(路径 MTU 发现) |
| IP_HDRINCL | 自定义 IP 头 | 应用层提供完整 IP 头(Raw socket) |
| IP_MULTICAST_TTL | 多播 TTL | 控制多播传播范围 |
| IP_MULTICAST_IF | 多播网卡 | 指定多播使用的本地网卡 |
| IP_MULTICAST_LOOP | 多播回环 | 控制多播是否回送给本机 |
| IP_ADD_MEMBERSHIP | 加入多播组 | 加入 IPv4 多播组 |
| IP_DROP_MEMBERSHIP | 退出多播组 | 退出多播组 |
4. IPv6 层选项(IPPROTO_IPV6)
| 选项 | 作用 |
|---|---|
| IPV6_V6ONLY | 限制 socket 只接受 IPv6,不允许 IPv4-mapped |
| IPV6_UNICAST_HOPS | IPv6 的 Hop Limit(类似 TTL) |
| IPV6_MULTICAST_HOPS | 多播 hop limit |
| IPV6_MULTICAST_LOOP | 多播回环 |
| IPV6_ADD_MEMBERSHIP / DROP_MEMBERSHIP | 加入/退出 IPv6 多播组 |
| IPV6_RECVPKTINFO | 接收 IPv6 包信息(源地址、接口等) |
5. UDP 层选项(IPPROTO_UDP)
UDP 没有 TCP 那么多选项,主要是:
| 选项 | 作用 |
|---|---|
| UDP_CORK | 聚合数据后再发(类似 TCP_CORK) |
| UDP_GRO | 允许接收大型报文(GRO 聚合) |
6. Ktor/JVM 暴露的常用 SocketOptions
Ktor 封装的是常见且跨平台的:
| Ktor 选项 | 对应底层 | 作用 |
|---|---|---|
| typeOfService | IP_TOS | 设置 IP TOS / DSCP |
| reuseAddress | SO_REUSEADDR | 端口重用(TIME_WAIT 时可绑定) |
| reusePort | SO_REUSEPORT | 多进程/线程共享同端口(Linux) |
| sendBufferSize | SO_SNDBUF | 发送缓冲区大小 |
| receiveBufferSize | SO_RCVBUF | 接收缓冲区大小 |
| broadcast(UDP) | SO_BROADCAST | 是否允许 UDP 广播 |
| noDelay(TCP) | TCP_NODELAY | 禁用 Nagle(减少延迟) |
| lingerSeconds | SO_LINGER | 控制 close() 行为 |
| keepAlive | SO_KEEPALIVE | 是否启用 TCP keepalive |
| socketTimeout | SO_RCVTIMEO + SO_SNDTIMEO | 读写超时 |
Ktor 已做跨平台兼容:
在不支持的系统上,这些选项会被"静默忽略"(Ktor 注释中已说明)。