Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Linux系统服务端口的那些事
Search
yongboy
June 28, 2014
Technology
2
1.5k
Linux系统服务端口的那些事
了解Linux服务器端口的用途和局限,以及如何突破端口限制。
yongboy
June 28, 2014
Tweet
Share
Other Decks in Technology
See All in Technology
面倒な作業はAIにおまかせ。Flutter開発をスマートに効率化
ruideengineer
0
170
fukabori.fm 出張版: 売上高617億円と高稼働率を陰で支えた社内ツール開発のあれこれ話 / 20250704 Yoshimasa Iwase & Tomoo Morikawa
shift_evolve
PRO
2
6.4k
開発生産性を組織全体の「生産性」へ! 部門間連携の壁を越える実践的ステップ
sudo5in5k
2
5.9k
第4回Snowflake 金融ユーザー会 Snowflake summit recap
tamaoki
1
210
Tech-Verse 2025 Global CTO Session
lycorptech_jp
PRO
0
1.6k
開発生産性を測る前にやるべきこと - 組織改善の実践 / Before Measuring Dev Productivity
kaonavi
0
110
CursorによるPMO業務の代替 / Automating PMO Tasks with Cursor
motoyoshi_kakaku
2
920
論文紹介:LLMDet (CVPR2025 Highlight)
tattaka
0
300
Zephyr RTOSを使った開発コンペに参加した件
iotengineer22
1
200
AI導入の理想と現実~コストと浸透〜
oprstchn
0
190
整頓のジレンマとの戦い〜Tidy First?で振り返る事業とキャリアの歩み〜/Fighting the tidiness dilemma〜Business and Career Milestones Reflected on in Tidy First?〜
bitkey
2
14k
United Airlines Customer Service– Call 1-833-341-3142 Now!
airhelp
0
160
Featured
See All Featured
Building an army of robots
kneath
306
45k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
960
Unsuck your backbone
ammeep
671
58k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
126
52k
Building a Modern Day E-commerce SEO Strategy
aleyda
42
7.4k
Gamification - CAS2011
davidbonilla
81
5.3k
Done Done
chrislema
184
16k
Code Reviewing Like a Champion
maltzj
524
40k
GitHub's CSS Performance
jonrohan
1031
460k
Raft: Consensus for Rubyists
vanstee
140
7k
Rebuilding a faster, lazier Slack
samanthasiow
82
9.1k
Transcript
Linux服务器端口的那些事 了解端口的用途和局限,以及如何突破端口限制 聂永@2014/06/26
目录 目录 IP和协议端口 网络四元组、二元组 突破端口限制 代码绑定IP和端口 外部程序绑定IP和端口 地址和TIME_WAIT 服务器地址重用和释放 演示和用途
数据进入栈封装过程
IP地址位置 IP报文 IP地址属于IP数据报,标识源主机和目标主机
协议端口在TCP数据包中位置 只有TCP数据包头部中包含端口 端口号和TCP服务器进程存在映射关系 端口,具有数据包路由作用 TCP传输层根据端口路由数据包到服务器程序所申请的缓存队列中
协议端口用途 一台服务器好比一座院子 IP地址比作院子大门;一座院子对应至少一个大门 每一个具体的服务程序进程好比一个房子 端口号好比进入房间的门
一个房间至少一个门 服务器程序可以决定由哪一个大门才能进入房间 以太网帧根据IP地址决定投递主机位置,端口决定数据报送达应用程 序映射 服务器内核接收的数据将根据端口进行路由传递到对应程序中
协议端口的一些常识 16位表示 范围:从0 到65535(2^16-1) 已知端口号[0,1023],这些端口由IANA分配和控制 Linux下需要root权限才能使用
[1024,65535],可自由使用端口数量不超过64512个 但不要和已有服务进行冲突
UNP对网络四元组的解释 《UNIX网络编程卷1:套接字联网API(第3版)》(简称UNP)解 释: 一个TCP连接的套接字对(socket pari)是一个定义该连接的两个端点 的四元组,即本地IP地址、本地TCP端口号、外地IP地址、外地TCP 端口号。套接字对唯一标识一个网络上的每个TCP连接。
...... 标识每个端点的两个值(IP地址和端口号)通常称为一个套接字。
四元组解释 仅针对TCP IP用于标识通讯的机器,端口号用于标识通信的进程。 网络四元组,一个完整TCP连接参阅双方体现: {请求者本机IP地址,请求者本机端口,目标IP地址,目标端口} 一次TCP请求必须把自身IP、PORT以及目标IP、目标PORT都要携
带上
Linux系统端口范围 默认范围:1~65535 0-1023已知端口,已被分配,需要ROOT权限 可被自由使用端口范围:65535 - 1024 ≈
64000 查看Linux系统默认可使用端口范围: sysctl -a | grep 'net.ipv4.ip_local_port_range' 32768 61000 修改其端口范围: sysctl -w net.ipv4.ip_local_port_range=1024 65535 保存修改: sysctl -p 持久化
如何突破端口数量限制 默认情况下,系统对外发出的请求数量受限于可用端口数量! 网络四元组中{本机IP,本机Port}两元组表示一个套接字 一个套接字表示系统可以向外请求的一个完整的TCP连接 套接字的数量表示系统可对外请求的完整TCP连接数量!
本机可用TCP套接字数量 = 本机IP数量 * 本机可用端口数量 绑定10个IP地址,自由可用端口约64000,那么可用端口数量 10 * 64000 = 640000,64万!
其它受限条件 打开文件句柄的限制,必须要大于可用端口数量 系统内存限制 每一个连接最少占用4K内存,连接数*4K = 需要的内存数,要求系 统内存要能够完全满足
线程/IO模型,非阻塞型:同步非阻塞/异步非阻塞,不用占满CPU 系统绑定的物理网卡数量受限
虚拟IP来帮忙 添加物理网卡,费时费劲,不太方便 可分配一个或多个IP地址给系统的虚拟IP,很方便! Linux添加虚拟IP: ifconfig eth0:0 192.168.190.151
netmask 255.255.255.0 up 写入/etc/rc.local里可防止重启后丢失 试试Docker 已经释出Docker 1.0,可以尝试一下
代码指定IP和端口 C语言如何做 struct sockaddr_in clnt_addr; clnt_addr.sin_addr.s_addr = inet_addr(server_ip); clnt_addr.sin_port
= htons(server_port); Java如何做 java.net.InetSocketAddress 此类实现 IP 套接字地址(IP 地址 + 端口号)。它还可以是一个对 (主机名 + 端口号),在此情况下,将尝试解析主机名。 如果解析失败,则该地址将被视为未解析地址,但是其在某些情形下 仍然可以使用,比如通过代理连接。 服务器程序可以绑定所有可用IP地址 客户端请求者只能绑定一个具体IP(若非手动指定,系统默认选择可 用IP)
代码示范 服务器端示范程序,绑定IP和端口 https://gist.github.com/yongboy/37875ad2476b0a8cab90 客户端示范程序,可绑定所有可用IP和端口,对外发出海量请求 https://gist.github.com/yongboy/5476214 后面会演示
指定已有程序绑定IP/端口? 已有程序,如何修改其绑定的IP地址和端口 ? 修改配置文件 试试linux系统的bindp小程序吧! https://github.com/yongboy/bindp
可在运行之前硬绑定的指定IP和端口 原理: LD_PRELOAD,允许定义在程序运行前优先加载的动态链接库 如何使用: BIND_ADDR="your ip" BIND_PORT="your port" LD_PRELOAD=/your_path/bindp.so the real command ...
bindp + nginx + curl的示范1 nginx默认80端口, 设置nginx以8888端口进行启动 BIND_PORT="8888" LD_PRELOAD=/home/yongboy/bindp/bindp.so
/usr/sbin/nginx -c /etc/nginx/nginx.conf 测试端准备 绑定特定IP和端口: BIND_ADDR="192.168.192.141" BIND_PORT="16888" LD_PRELOAD=/home/yongboy/bindp/bindp.so curl http://192.168.192.130 nginx日志输出:
bindp + nginx + curl的示范2 测试端第一次请求 BIND_ADDR="192.168.192.141" BIND_PORT="16888" LD_PRELOAD=/home/yongboy/bindp/bindp.so
curl http://192.168.192.130 测试端第二次请求(间隔很短,不超过10秒钟) BIND_ADDR="192.168.192.141" BIND_PORT="16888" LD_PRELOAD=/home/yongboy/bindp/bindp.so curl http://192.168.192.130 持续观察Nginx日志输出
端口释放以及TIME_WAIT阶段 端口释放发生在四次挥手期间 主动关闭方产生TIME_WAIT 主动方最后一次发送挥手时计算 等待真正关闭
占用端口何时释放? 测试端连接虽已关闭,但被占用端口系统不会立即释放 主动关闭方产生TIME_WAIT TIME_WAIT需要等待分组彻底消失,2倍MSL(Maximum Segment Life), 1MSL
= 30s(Linux系统) sysctl -a | grep net.ipv4.tcp_fin_timeout net.ipv4.tcp_fin_timeout = 60 原因: 1)TIME_WAIT可确保系统有足够时间让对端收到Fin ACK,如果 对方没有收到Fin Ack,会触发重发Fin ACK,2个MSL时间周期 2)系统有足够的时间让已关闭的连接不会跟后面的连接混淆(避免 连接被重用时,可能路由器层面缓存IP数据包,导致混淆) 3)TIME_WAIT下一站是真正的关闭
服务器程序地址重用 服务器程序启动时需要显式标注自身需要地址重用 C语言版: int reuseaddr_on = 1; if
(setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on, sizeof(reuseaddr_on))) err(1, "setsockopt failed"); Java&Netty 版本 Java: ServerSocket socket = new ServerSocket(); socket.setReuseAddress(true); Netty 3.x bootstrap.setOption("reuseAddress", true); Netty 4.x/5.x ServerBootstrap server = new ServerBootstrap(); server.group(bossGroup, workerGroup) .option(ChannelOption.SO_REUSEADDR, true); 演示实际效果 ?
服务器程序地址重用2 不指定地址重用,在短时间内(60S内)再次重启: server: bind failed: Address already in use
地址重用 可以快速重启 同一端口可以被多次使用,但需要绑定到不同IP上 不同IP绑定同一端口 绑定不存在的IP地址: bind failed: Cannot assign requested address 不指定具体IP,意味着继续使用默认IP,其它进程绑定端口 bind failed: Address already in use 已绑定的指定IP和端口,其它进程再次绑定: bind failed: Address already in use
服务器如何快速回收端口? Linux系统默认值: net.ipv4.tcp_tw_reuse = 0 net.ipv4.tcp_tw_recycle =
0 默认都是关闭 tcp_tw_recycle,比较激进,若开启需同时设置 tcp_timestamps=1 不建议修改 修改可能会产生意想不到的问题 服务器端尽量不要主动关闭连接
Linux一些小工具 通过端口查看进程 lsof -i:port 进程查看端口 netstat
–nltp|grep 进程号 SS命令
突破端口限制的示范/用途 若有时间,演示从测试机发出超过64000个对外请求 只要机器性能够好,可以发出超过100万个并发长连接请求 绑定IP和端口,突破端口数量限制,用途: 访问代理服务器
内网/外网百万长连接压力测试 ......
谢谢聆听!