1. 一般来讲,在我们写一个server的时候,会用到SO_REUSEADDR,因为,当server正在工作的时候,需要重启,这时候,可能server的一些子进程还在工作,也或者一些连接还处于time_wait状态,而且time_wait状态的时间一般比较长,如果没有SO_REUSEADDR,则会因为端口被占用而bind失败,无法启动server,实例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (!is_resource($socket)) { echo 'Unable to create socket: '. socket_strerror(socket_last_error()) . PHP_EOL; } if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) { echo 'Unable to set option on socket: '. socket_strerror(socket_last_error()) . PHP_EOL; } if (!socket_bind($socket, '127.0.0.1', 1223)) { echo 'Unable to bind socket: '. socket_strerror(socket_last_error()) . PHP_EOL; } $rval = socket_get_option($socket, SOL_SOCKET, SO_REUSEADDR); if ($rval === false) { echo 'Unable to get socket option: '. socket_strerror(socket_last_error()) . PHP_EOL; } else if ($rval !== 0) { echo 'SO_REUSEADDR is set on socket !' . PHP_EOL; } |
注意:
端口被占用后,不是listen是否能够成功,主要是bind能否成功。
2. 对于一个client来讲,如果总是疯狂地连接某个IP的同一个端口,并且连接完之后主动关闭连接,会导致大量的time_wait状态的连接,如果系统没有设置 net.ipv4.tcp_tw_reuse = 1 , 则会导致bind失败(虽然该bind的是隐式的)