【网络调优】Linux网络端口随机分配问题
1.Linux端口基础
1.端口号0不使用
2.端口号1-1023,系统默认只给root使用
3.端口号1024-4999由客户端程序自由分配
4.端口号5000-65535由服务器程序自由分配
2.Linux默认随机端口范围
TCP/IP协议栈从ip_local_port_range中随机选取源端口时,会排除ip_local_reserved_ports中定义的端口,因此不会出现端口被占用导致服务无法启动的问题。使用net.ipv4.ip_local_port_range参数,规划出一段端口段预留作为服务的端口,这种方法是可以解决当前问题。
一般Linux的默认随机端口范围是:32768 - 60999 (可以通过查看配置文件的方式来获取)
当客户端port设置为0时,Linux会为和客户端在随机范围内分配一个随机的端口号,客户端分配随机端口号实例代码:
int main initTcpSocketClient() {
int sock_fd;
struct sockaddr_in addr;
socklen_t socklen;
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = 0; // 绑定随机端口
addr.sin_addr.s_addr = INADDR_ANY;
socklen = sizeof(addr);
if (bind(sock_fd, (struct sockaddr *)&addr, socklen)) {
perror("bind error");
return -1;
}
// 获取系统随机分配的端口号
getsockname(sock_fd, (sockaddr*)&addr, &socklen);
MONITORLOGE("initTcpSocketClient%u\n", ntohs(addr.sin_port));
return 0;
}
2.1 修改Linux内核有关修改参数
2.1.1.通过修改配置文件的方式修改
设置端口参数的配置文件:/etc/sysctl.conf
设置Linux端口的随机范围:net.ipv4.ip_local_port_range = 60000 65535
echo "net.ipv4.ip_local_port_range = 60000 65535" >> /etc/sysctl.conf
设置Linux保留端口范围(内部服务固定的监听端口):net.ipv4.ip_local_reserved_ports = 8014,60011-60014
执行后生效配置:sysctl -p /etc/sysctl.conf
如果没有生效则reboot一下系统,即可生效
2.1.2 直接修改内存中的配置项
直接修改内存配置项的方法无需reboot系统,但是一旦reboot后当前配置即失效
1.获取当前系统的Linux端口随机范围:
cat /proc/sys/net/ipv4/ip_local_port_range
2.修改当前系统Linux端口的随机范围:
echo 13400 60800 > /proc/sys/net/ipv4/ip_local_port_range
修改完后可以再cat出来确认一下
3.获取当前系统的保留端口:
cat /proc/sys/net/ipv4/ip_local_reserved_ports
4.修改当前系统的保留端口:
echo 46555,12345 > /proc/sys/net/ipv4/ip_local_reserved_ports
3.Linux端口资源情况获取命令
1.获取当前系统中所有正在使用的server端口
netstat -tunlp
2.查看当前白名单端口情况
iptables --list
3.获取当前占用端口的进程pid号
netstat -tulnp | grep 12345 | awk '{print $7}' | cut -d'/' -f1
4.问题经验
最近开发中遇到一个问题,在板子升级完成并重启后偶现(极低概率)系统中的一个服务的socket,bind faild的情况,因后续没有再次复现,所以通过已有的log分析,可能是因为某些client随机分配port导致正好挤占了服务所用到的port资源上,导致服务bind失败,如果是此种情况,可以考虑将目前用到的所有port口都加入到ip_local_reserved_ports中,防止后续出现port资源被Linux随机分配挤占的情况。