Socket 编程之 SO_REUSEADDR & SO_REUSEPORT 全揭秘

SO_REUSEADDR 和 SO_REUSEPORT 是 socket 编程中非常重要的两个套接字选项,同时也在实际的网络编程中经常会用到。从名字能够大概了解这两个选项的功能:前者是重用地址,后者是重用端口;概括一下就是,前者允许以相同的端口绑定不同的地址,后者允许以相同的地址再绑定相同的端口。 这两个套接字选项都是基于现实的网络编程问题而设计出来的,我会在本文中分析这两个选项实际解决的问题,能为网络编程带来哪些优势,其本身又有哪些劣势和副作用。最后我会再讲一讲这两个套接字选项在类 Unix 操作系统的不同平台上的实现有哪些异同,希望能为读者以后编写跨平台的可移植程序提供一点启发和参考。


TCP Keep-Alives 的原理和应用

今年初的时候我为 Go 语言实现了一个完整的 TCP Keep-Alives 机制。TCP keepalive 虽然是 TCP 协议标准却不是 POSIX 标准,然而用来支持 TCP keepalive 的三个套接字选项 `TCP_KEEPIDLE`、`TCP_KEEPINTVL` 和 `TCP_KEEPCNT` 却在类 Unix 操作系统和 Windows 上被广泛地支持,于是 Go 作为一个跨平台的编程语言,其 TCP keepalive 的支持必须尽量覆盖所有提供了这三个套接字选项的操作系统:Linux、macOS、Windows、*BSD (FreeBSD/DragonflyBSD/OpenBSD/NetBSD) 以及 SunOS (Solaris/illumos)。 期间我深入调研了一下 TCP keepalive 在这些不同平台上的具体实现的异同,以及踩过不少坑,在把这个功能提交到 Go 语言的代码仓库之后,算是对这方面熟稔了,后来我还给 redis、libevent、libuv 和 curl 等一众知名的开源项目都实现/补充了 TCP keepalive 机制,现在通过本文分享一下相关的经验,希望能对那些需要编写跨平台程序的读者有所帮助。


TCP 连接管理和数据传输全揭秘

相对于 UDP 这样的无连接 (connection-less) 协议,TCP 是一种连接导向 (connection-oriented) 的可靠性协议,其目标是在不可靠的网络环境中实现可靠的数据传输。我们知道网络环境是复杂多变的,网络通信本质上是一种不可靠通信,要在不可靠的网络中实现 TCP 这样的可靠通信协议需要做很多工作:基于 TCP 协议的双端通信,在数据传输前需要建立一条连接,然后基于该连接来进行可靠的通信;在传输数据的过程中还要利用校验和、序列号、确认应答 (ACK)、重发控制、连接管理以及流量窗口控制等机制来实现可靠性传输;最后在终止连接的过程中也要处理一些异常情况以保证顺利关闭连接。