地址复用setsockopt()
Cp from戴墨镜.
1.setsockopt()作用
socket关闭之后,操作系统不会立即收回对端口的控制权,而是要经历一个等待阶段。此时对这个端口绑定就会出错。想要立即进行绑定,就必须先设置SO_REUSEADDR.
或者在关闭socket的时候,使用setsockopt设置SO_REUSEADDR。才会消除等待时间。
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
sockfd: 套接字描述字
level: 选项定义的层次;支持SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6.
optname: 需要设置的选项
optval: 指针,指向存放选项值的缓冲区
optlen: optval缓冲区长度
- level SOL_SOCKET
选项名称 | 说明 | 数据类型 |
---|---|---|
SO_BROADCAST | 允许发送广播数据 | int |
SO_DEBUG | 允许调试 | int |
SO_DONTROUTE | 不查找路由 | int |
SO_ERROR | 获得套接字错误 | int |
SO_KEEPALIVE | 保持连接 | int |
SO_LINGER | 延迟关闭连接 | struct linger |
SO_OOBINLINE | 带外数据放入正常数据流 | int |
SO_RCVBUF | 接收缓冲区大小 | int |
SO_SNDBUF | 发送缓冲区大小 | int |
SO_RCVLOWAT | 接收缓冲区下限 | int |
SO_SNDLOWAT | 发送缓冲区下限 | int |
SO_RCVTIMEO | 接收超时 | struct timeval |
SO_SNDTIMEO | 发送超时 | struct timeval |
SO_REUSERADDR | 允许重用本地地址和端口 | int |
SO_TYPE | 获得套接字类型 | int |
SO_BSDCOMPAT | 与BSD系统兼容 | int |
二、简单用法
//地址复用
void set_reuseaddr(int sockfd, int optval)
{
int on = (optval != 0) ? 1 : 0;
//int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
/* sockfd:标识一个套接口的描述字。
level:选项定义的层次;支持SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6。
optname:需设置的选项。
optval:指针,指向存放选项值的缓冲区。
optlen:optval缓冲区长度。
返回值: 成功返回0,失败返回 -1. */
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
ERR_EXIT("setsockopt SO_REUSEADDR");
}
//端口复用
void set_reuseport(int sockfd, int optval)
{
#ifdef SO_REUSEPORT
int on = (optval != 0) ? 1 : 0;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0)
ERR_EXIT("setsockopt SO_REUSEPORT");
#else
fprintf(stderr, "SO_REUSEPORT is not supported.
");
#endif //SO_REUSEPORT
}