简介
开一篇文章来专门分析TCP常用的参数设定。
libevent提供的修改选项
libevent关于tcp的选项主要放到evutil.c文件中。
关键函数
fcntl
在Linux
里面使用fcntl
可以对socket这个fd做一些查询调整。
O_NONBLOCK
提供了一个设置非阻塞方式的fd。
1 | int flags; |
FD_CLOEXEC
当执行成功之后将会自动释放掉fd。
If the FD_CLOEXEC bit is set, the file descriptor will automatically be closed during a successful execve(2). (If the execve(2) fails, the file descriptor is left open.) If he FD_CLOEXEC bit is not set, the file descriptor will remain open across an execve(2).
如果FD_CLOEXEC
位置设置了,这个文件描述字将会自动被关闭在execve(2)
函数执行成功时候。(如果execve(2)
失败了,文件描述字将继续开着。)如果FD_CLOEXEC
没有被设置,文件描述字将会保持打开状态即使执行了execve(2)
。
- 在创建socket的时候,也会指定
EVUTIL_SOCK_CLOEXEC
。
1 | if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { |
setsockopt
SO_REUSEADDR
原文注释:
REUSEADDR on Unix means, “don’t hang on to this address after the listener is closed.” On Windows, though, it means “don’t keep other processes from binding to this address while we’re using it.”
REUSEADDR 在Unix的意义,“不要挂起地址,当listener已经被关闭。”然而,在Windows,它的意义,“不用拒绝别的进程绑定此地址,当我们已经使用了它。”。
所以这个选项只在非Windows环境开启。
SO_REUSEPORT
原文注释:
REUSEPORT on Linux 3.9+ means, “Multiple servers (processes or threads) can bind to the same port if they each set the option.
在Linux 3.9+ 内核版本的意义,“多服务(进程或线程)能绑定相同端口,如果它们都设置了这个选项。”
IPV6_V6ONLY
将socket设置成只支持IPV6。
1 | int one = 1; |
TCP_DEFER_ACCEPT
原文注释:
TCP_DEFER_ACCEPT tells the kernel to call defer accept() only after data has arrived and ready to read
告诉内核延时调用accept()
,只有当其数据已经到达而且准备好读取时。
SO_KEEPALIVE
在listener
、http
当成accept
的socket才做了这个设定。
Enable sending of keep-alive messages on connection-oriented sockets. Expects an integer boolean flag.
允许发送keep-alive
消息在面向连接的sockets
上。
1 | int on = 1; |
SO_LINGER
LINGER:持续观察。
在libevent源码中,只有在benchmark测试代码里面用了一下。在平时游戏服务器里面是不要用这个开关,否则会让服务器直接卡死。
手册原文:
When enabled, a close(2) or shutdown(2) will not return until all queued messages for the socket have been successfully sent or the linger timeout has been reached. Otherwise, the call returns immediately and the closing is done in the background. When the socket is closed as part of exit(2), it always lingers in the background.
生效时,一个close(2)
或者shutdown(2)
函数将不会返回直到属于socket
全部队列数据都已经发送成功或持续观察超时时间已经到了。否则,调用之后将会立即返回而且关闭动作将会在后台继续执行。当socket
被关闭通过exit(2)
,它也将持续观察在后台。
SO_RCVBUF
1 | Sets or gets the maximum socket receive buffer in bytes. |
SO_SNDBUF
1 | Sets or gets the maximum socket send buffer in bytes. The |
dogecoin源码中如何处理
TCP_NODELAY
关闭了Nagle算法。这个在libevent里面没有提供。
Disable Nagle’s algorithm.
SO_REUSEADDR
当listener
已经关闭之后不要挂起这个地址。
Allow binding if the port is still in TIME_WAIT state after the program was closed and restarted.
允许绑定如果这个端口依然处在TIME_WAIT
状态,当程序被关闭或者重启了。
IPV6_V6ONLY
开启IPV6的socket。
SO_NOSIGPIPE
1 | Different way of disabling SIGPIPE on BSD |
libuv源码
大量的和libevent相同。
SO_OOBINLINE
1 | # |
TCP_KEEPIDLE
1 | # |
IP_MULTICAST_IF
用于UDP广播。
1 | if (addr_st.ss_family == AF_INET) { |
引用
- [1] fcntl-fd-cloexec
- [2] man7-socket7
- [3] Socket_002dLevel-Options
- [4] man-tcp