linux中ss实现原理,ss 详解

ss

用来显示处于活动状态的套接字信息。ss命令可以用来获取socket统计信息,它可以显示和netstat(参考https://www.jianshu.com/p/7630474c39b1)类似的内容。但ss的优势在于它能够显示更多更详细的有关TCP和连接状态的信息,而且比netstat更快速更高效。

当服务器的socket连接数量变得非常大时,无论是使用netstat命令还是直接cat /proc/net/tcp,执行速度都会很慢。可能你不会有切身的感受,但请相信我,当服务器维持的连接达到上万个的时候,使用netstat等于浪费 生命,而用ss才是节省时间。

天下武功唯快不破。ss快的秘诀在于,它利用到了TCP协议栈中tcp_diag。tcp_diag是一个用于分析统计的模块,可以获得Linux 内核中第一手的信息,这就确保了ss的快捷高效。当然,如果你的系统中没有tcp_diag,ss也可以正常运行,只是效率会变得稍慢。

参数(和netstat类似)-h:显示帮助信息;

-V:显示指令版本信息;

-n:不解析服务名称,以数字方式显示;

-a:显示所有的套接字;

-l:显示处于监听状态的套接字;

-o:显示计时器信息;

-m:显示套接字的内存使用情况;

-p:显示使用套接字的进程信息;

-i:显示内部的TCP信息;

-4:只显示ipv4的套接字;

-6:只显示ipv6的套接字;

-t:只显示tcp套接字;

-u:只显示udp套接字;

-d:只显示DCCP套接字;

-w:仅显示RAW套接字;

-x:仅显示UNIX域套接字。

示例[admin@localhost ~]# ss -t -a

State      Recv-Q Send-Q                            Local Address:Port                                Peer Address:Port

LISTEN      0      0                                            *:3306                                          *:*

LISTEN      0      0                                            *:http                                          *:*

LISTEN      0      0                                            *:ssh                                            *:*

LISTEN      0      0                                    127.0.0.1:smtp                                          *:*

ESTAB      0      0                                112.124.15.130:42071                              42.156.166.25:http

ESTAB      0      0                                112.124.15.130:ssh                              121.229.196.235:33398

显示统计信息[admin@localhost ~]# ss -s

Total: 172 (kernel 189)

TCP:  10 (estab 2, closed 4, orphaned 0, synrecv 0, timewait 0/0), ports 5

Transport Total    ip        IPv6

*        189      -        -

RAW      0        0        0

UDP      5        5        0

TCP      6        6        0

INET      11        11        0

FRAG      0        0        0

查看进程使用的socket[admin@localhost ~]# ss -pl

State      Recv-Q Send-Q                                Local Address:Port                                    Peer Address:Port

LISTEN      0      128                                              :::ssh                                              :::*        users:(("sshd",1292,4))

LISTEN      0      128                                              *:ssh                                                *:*        users:(("sshd",1292,3))

LISTEN      0      128                                      127.0.0.1:ipp                                                *:*        users:(("cupsd",1165,7))

LISTEN      0      128                                            ::1:ipp                                              :::*        users:(("cupsd",1165,6))

LISTEN      0      128                                              *:32957                                              *:*        users:(("rpc.statd",1104,9))

LISTEN      0      128                                              :::57637                                            :::*        users:(("rpc.statd",1104,11))

LISTEN      0      80                                              :::mysql                                            :::*        users:(("mysqld",1528,17))

LISTEN      0      128                                              *:6379                                              *:*        users:(("redis-server",1672,5))

LISTEN      0      128                                              :::6379                                              :::*        users:(("redis-server",1672,4))

LISTEN      0      128                                              :::sunrpc                                            :::*        users:(("rpcbind",1084,11))

LISTEN      0      128                                              *:sunrpc                                            *:*        users:(("rpcbind",1084,8))

LISTEN      0      128                                              *:http                                              *:*        users:(("nginx",1685,13),("nginx",3698,13),("nginx",3699,13))

关于Recv-Q和Send-Q状态

当 client 通过 connect 向 server 发出 SYN 包时,client 会维护一个 socket 等待队列,而 server 会维护一个 SYN 队列

此时进入半链接的状态,如果 socket 等待队列满了,server 则会丢弃,而 client 也会由此返回 connection time out;只要是 client 没有收到 SYN+ACK,3s 之后,client 会再次发送,如果依然没有收到,9s 之后会继续发送

半连接 syn 队列的长度为 max(64, /proc/sys/net/ipv4/tcp_max_syn_backlog)  决定

当 server 收到 client 的 SYN 包后,会返回 SYN, ACK 的包加以确认,client 的 TCP 协议栈会唤醒 socket 等待队列,发出 connect 调用

client 返回 ACK 的包后,server 会进入一个新的叫 accept 的队列,该队列的长度为 min(backlog, somaxconn),默认情况下,somaxconn 的值为 128,表示最多有 129 的 ESTAB 的连接等待 accept(),而 backlog 的值则由int listen(int sockfd, int backlog) (网络编程的一个参数)中的第二个参数指定。

当 accept 队列满了之后,即使 client 继续向 server 发送 ACK 的包,也会不被相应,此时,server 通过 /proc/sys/net/ipv4/tcp_abort_on_overflow 来决定如何返回,0 表示直接丢丢弃该 ACK,1 表示发送 RST 通知 client;相应的,client 则会分别返回 read timeout 或者 connection reset by peer。上面说的只是些理论,如果服务器不及时的调用 accept(),当 queue 满了之后,服务器并不会按照理论所述,不再对 SYN 进行应答,返回 ETIMEDOUT。

可以看到,整个 TCP stack 有如下的两个 queue:

1. 一个是 half open(syn queue) queue(max(tcp_max_syn_backlog, 64)),用来保存 SYN_SENT 以及 SYN_RECV 的信息。

2. 另外一个是 accept queue(min(somaxconn, backlog)),保存 ESTAB 的状态,但是调用 accept()。

使用 ss 获取到的 Recv-Q/Send-Q 在 LISTEN 状态以及非 LISTEN 状态所表达的含义是不同的。

LISTEN 状态: Recv-Q 表示的当前等待服务端调用 accept 完成三次握手的 listen backlog 数值,也就是说,当客户端通过 connect() 去连接正在 listen() 的服务端时,这些连接会一直处于这个 queue 里面直到被服务端 accept();Send-Q 表示的则是最大的 listen backlog 数值,这就就是上面提到的 min(backlog, somaxconn) 的值。

其余状态: 非 LISTEN 状态,代表缓冲区字节数量。Recv-Q 表示 receive queue 中的 bytes 数量;Send-Q 表示 send queue 中的 bytes 数值。

查看tcp_diag代码static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, void *_info) {

const struct tcp_sock *tp = tcp_sk(sk);

struct tcp_info *info = _info;

if (sk->sk_state == TCP_LISTEN) {

r->idiag_rqueue = sk->sk_ack_backlog;

r->idiag_wqueue = sk->sk_max_ack_backlog;

} else {

r->idiag_rqueue = tp->rcv_nxt - tp->copied_seq;

r->idiag_wqueue = tp->write_seq - tp->snd_una;

}

if (info != NULL)

tcp_get_info(sk, info);

}

显示更多的信息

-o, --options 显示时间信息(定时器)

-m, --memory 显示 socket 使用的内存

-i, --info 显示更多 TCP 内部的信息

-s 显示统计信息~ # ss -a -t -o -4

State       Recv-Q Send-Q                                            Local Address:Port                                                Peer Address:Port

LISTEN      0      128                                                           *:openvms-sysipc                                                        *:*

ESTAB       0      0                                                172.16.132.189:ssh                                                172.16.132.93:hs-port  timer:(keepalive,65min,0)

ESTAB       0      0                                                    10.0.64.19:49462                                                10.0.64.107:61616

ESTAB       0      0                                                172.16.132.189:ssh                                                172.16.132.85:63934    timer:(keepalive,38min,0)

ESTAB       0      0                                                    10.0.64.19:60569                                                10.0.64.107:61616

这个输出更上次输出相比,多了一个timer输出。这个输出描述的是tcp socket上的定时器,在说明这个之前先了解一下linux对一个tcp socket可能设置的定时器。

tcp socket总共有7个定时器,通过4个timer实现。分别是

通过icsk_retransmit_timer实现的重传定时器、零窗口探测定时器;通过sk_timer实现的连接建立定时器、保活定时器和FIN_WAIT_2定时器;通过icsk_delack_timer实现的延时ack定时器;以及TIME_WAIT定时器。

我们看一下ss的代码static const char *tmr_name[] = {

"off",

"on",

"keepalive",

"timewait",

"persist",

"unknown"

};if (show_options) {

if (r->idiag_timer) {

if (r->idiag_timer > 4)

r->idiag_timer = 5;

printf(" timer:(%s,%s,%d)",

tmr_name[r->idiag_timer],

print_ms_timer(r->idiag_expires),

r->idiag_retrans);

}

}

对应的内核代码是if (icsk->icsk_pending == ICSK_TIME_RETRANS) {

r->idiag_timer = 1;

r->idiag_retrans = icsk->icsk_retransmits;

r->idiag_expires = EXPIRES_IN_MS(icsk->icsk_timeout);

} else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {

r->idiag_timer = 4;

r->idiag_retrans = icsk->icsk_probes_out;

r->idiag_expires = EXPIRES_IN_MS(icsk->icsk_timeout);

} else if (timer_pending(&sk->sk_timer)) {

r->idiag_timer = 2;

r->idiag_retrans = icsk->icsk_probes_out;

r->idiag_expires = EXPIRES_IN_MS(sk->sk_timer.expires);

} else {

r->idiag_timer = 0;

r->idiag_expires = 0;

}static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, struct sk_buff *skb, int ext, u32 pid,

u32 seq, u16 nlmsg_flags, const struct nlmsghdr *unlh){

long tmo;

struct inet_diag_msg *r;

const unsigned char *previous_tail = skb_tail_pointer(skb);

struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq,

unlh->nlmsg_type, sizeof(*r));

r = NLMSG_DATA(nlh);

BUG_ON(tw->tw_state != TCP_TIME_WAIT);

nlh->nlmsg_flags = nlmsg_flags;

tmo = tw->tw_ttd - jiffies;

if (tmo 

tmo = 0;

r->idiag_family = tw->tw_family;

r->idiag_retrans = 0;

r->id.idiag_if = tw->tw_bound_dev_if;

r->id.idiag_cookie[0] = (u32)(unsigned long)tw;

r->id.idiag_cookie[1] = (u32)(((unsigned long)tw >> 31) >> 1);

r->id.idiag_sport = tw->tw_sport;

r->id.idiag_dport = tw->tw_dport;

r->id.idiag_src[0] = tw->tw_rcv_saddr;

r->id.idiag_dst[0] = tw->tw_daddr;

r->idiag_state = tw->tw_substate;

r->idiag_timer = 3;

r->idiag_expires = DIV_ROUND_UP(tmo * 1000, HZ);

r->idiag_rqueue = 0;

r->idiag_wqueue = 0;

r->idiag_uid = 0;

r->idiag_inode = 0;

timer的输出含义就是(类型,过期时间,重试次数),这里说一下类型的含义:

off: 当前socket没有timer

on: 重传timer

keepalive:连接建立timer or fin_wait_2 timer or 保活timer;具体是那个timer,可以根据连接的状态来确定。

timewait: TIME_WAITtimer

persist:零窗口探测timer

dst/src dport/sport 语法

可以通过 dst/src/dport/sprot 语法来过滤连接的来源和目标,来源端口和目标端口。

匹配远程地址和端口号$ ss dst 192.168.1.5

$ ss dst 192.168.119.113:http

$ ss dst 192.168.119.113:443

将本地或者远程端口和一个数比较,可以使用下面的语法做端口号的过滤:$ ss dport OP PORT

$ ss sport OP PORT

OP 可以代表以下任意一个:<=le小于或等于某个端口号

>=ge大于或等于某个端口号

==eq等于某个端口号

!=ne不等于某个端口号

>gt大于某个端口号

下面是一个简单的 demo(注意,需要对尖括号使用转义符):$ ss -tunl sport lt 50

$ ss -tunl sport \< 50

$  ss dport = :8080 or sport = :8080

ss 命令还可以通过 TCP 连接的状态进程过滤,支持的 TCP 协议中的状态有:established

syn-sent

syn-recv

fin-wait-1

fin-wait-2

time-wait

closed

close-wait

last-ack

listening

closing

除了上面的 TCP 状态,还可以使用下面这些状态:all列出所有的 TCP 状态。

connected列出除了 listening 和 closing 之外的所有 TCP 状态。

synchronized列出除了 syn-sent 之外的所有 TCP 状态。

bucket列出 maintained 的状态,如:time-wait 和 syn-recv。

big列出和 bucket 相反的状态。

使用 ipv4 时的过滤语法如下:

使用 ipv6 时的过滤语法如下:1$ ss -6 state filter

下面的两种写法是等价的,要有使用 \ 转义小括号,要么使用单引号括起来:$ ss -4n state listening \( dport = :ssh\)

$ ss -4n state listening '( dport = :ssh )'

找出打开套接字/端口应用程序[admin@localhost ~]# ss -pl | grep3306

00*:3306*:* users:(("mysqld",1718,10))ss -o state established '( dport = :smtp or sport = :smtp )' 显示所有已建立的SMTP连接

ss -o state established '( dport = :http or sport = :http )' 显示所有已建立的HTTP连接

ss -o state established '( dport = :8080 or sport = :8080 )'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/443522.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hibernate3.X实现基于CLOB字段类型的注解方式:

一&#xff1a;Hibernate3.X实现基于CLOB字段类型的注解方式的例子&#xff1a;下面直接上代码&#xff1a; 二&#xff1a;UserInfo.java package cn.gov.csrc.cms.model;import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity;…

linux mint安装步骤,Linux mint 安装步骤

##Linux mint 安装步骤##家里的笔记本以前一直用Deepin系统&#xff0c;但是Deepin系统的wifi实在是太慢了。还有就是启动软件是有时候总没响应&#xff0c;卡死机。 最近重装系统&#xff0c;选择了mint ,在这里记录下安装步骤。###1.制作U盘启动盘###下载iso文件&#xff0c;…

linux 商业游戏,Ubuntu下安装试玩原生Linux版商业游戏Braid

这款原生Linux版商业游戏Braid国外出售价大约在80美元左右。每年在Linux平台上发布的原生商业游戏是屈指可数&#xff0c;而且这些游戏的质量也是参差不齐。不过这款原生Linux版商业游戏Braid还是值得一玩的&#xff0c;这款Braid游戏创意十足&#xff0c;您可以通过拼图和时间…

linux centos 7 crontab 启动,CentOS 7 Linux执行crontab 计划任务实操 - 好应网

[inlosc_lg_title]一、环境准备[/inlosc_lg_title]yum install vixie-cron #安装定时任务插件yum install crontabs #安装定时任务crontabs/bin/systemctl restart crond.service #启动服务/bin/systemctl reload crond.service #重新载入配置/bin/systemctl status crond.serv…

变量的初始化与使用C语言程序注释,c - (为什么)使用未初始化的变量未定义行为?...

C标准为编译器提供了很大的优势来执行优化。 如果您假设一个简单的程序模型&#xff0c;其中未初始化的内存被设置为某个随机位模式&#xff0c;并且所有操作都按照它们的写入顺序执行&#xff0c;那么这些优化的后果可能会令人惊讶。注意&#xff1a;以下示例仅有效&#xff0…

三羊献瑞c语言编程入门,蓝桥杯-三羊献瑞,

蓝桥杯-三羊献瑞&#xff0c;更多精彩文章请关注公众号『大海的BLOG』问题观察下面的加法算式&#xff1a;祥 瑞 生 辉 三 羊 献 瑞----------------三 羊 生 瑞 气其中&#xff0c;相同的汉字代表相同的数字&#xff0c;不同的汉字代表不同的数字&#xff0c;‘三’和‘祥’不…

Struts2.3接收post方式提交的表单参数的方式

一&#xff1a;方式一&#xff1a;通过request来获取&#xff0c;首先让action实现ServletRequestAware接口&#xff0c;然后通过request来获取提交的参数&#xff0c;代码如下: package cn.gov.csrc.flight.action;import java.util.HashMap; import java.util.List; import j…

倒果汁c语言,水果榨汁补维生素C?这些补维生素的错误别再犯了

原标题&#xff1a;水果榨汁补维生素C&#xff1f;这些补维生素的错误别再犯了蔬菜和水果作为维生素C、矿物质和植物纤维的重要来源&#xff0c;是每天餐桌上都要出现的食物&#xff0c;一旦水果蔬菜吃不够&#xff0c;身体就会开始找你麻烦。在处理蔬菜水果的时候&#xff0c;…

dos和linux有关系吗,DOS和Linux近年来的发展比较

大家都听说过Linux操作系统吧&#xff01;Linux诞生于20世纪的90年代初&#xff0c;于90年代末开始出名并在许多人中开始了实际使用。著名的“开放源代码”运动更是使新的Linux程序不断出现&#xff0c;使Linux得到了进一步的发展&#xff0c;尤其是在服务器领域得到了较大的应…

c语言中二维数组的结构体,怎么才能把结构体里面的二维数组打印出来?

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼萌新一位&#xff0c;学到结构体在做作业&#xff0c;遇到了这个问题。求提示出现这样的报错&#xff1a;[Error] cannot convert char (*)[20] to char* for argument 5 to void HeroShow(int, int, char*, char*, char*, char*)#…

android中资源文件的两种访问方式,Android_Android学习笔记-保存文件(Saving Files),Android设备有两种文件存储区域 - phpStudy...

Android学习笔记-保存文件(Saving Files)Android设备有两种文件存储区域:内部存储和外部存储 ("internal" and "external" storage)。这名字来自早期Android&#xff0c;那时大多数Android设备提供两种存储方式:内置的非易失的内存(内部存储)和可移动的存储…

Struts2.3,s:iterator,c:forEach遍历map中的list集合

一&#xff1a;首先是<s:iterator></s:iterator>遍历map中的list集合&#xff0c;代码如下&#xff1a; 1.首先是后台代码&#xff0c;包括定义map和给map中赋值&#xff0c;代码如下&#xff1a; package cn.gov.csrc.cms.action;import java.util.HashMap; impo…

android 判断对象,Android网络判断知识小结

Android中判断当前网络是否可用应用场景&#xff1a;实现判断当前网络是否可用当前有可用网络&#xff0c;如下图&#xff1a;当前没有可用网络&#xff0c;如下图&#xff1a;实现步骤&#xff1a;1、获取ConnectivityManager对象Context context activity.getApplicationCon…

android fragment动画,Fragment 的过场动画

Fragment 的过场动画Android,Fragment,动画2018.08.03在 Android 开发中&#xff0c;有些应用对页面的过场动画要求比较高&#xff0c;他们中期望给用户提供一个良好的用户体验。适当的过场动画可以减少用户在页面加载时期等待的焦虑&#xff0c;因为让他们看一个动画&#xff…

android 联系人批量插入,GitHub - Atinerlengs/InsertDemo: android 简单的批量插入通话记录、联系人、短信demo...

[toc]批量插入批量插入通话记录下面是添加通话数据的代码&#xff0c;我们自己去构造Tb_calllogs数据&#xff0c;里面可以添加通话记录数据字段&#xff0c;由于是个简单的demo&#xff0c;所以只加了number、callType、date、callDuration。/*** 添加通话数据** throws Remot…

html页面按钮删除一条数据库,需要添加一个删除按钮到一个HTML表格从数据库中删除记录与消息...

IDNameCodeActiveEdit<?php foreach($nurseries->result() as $nursery) { ?><?php echo $nursery->id; ?><?php echo $nursery->name; ?><?php echo $nursery->code; ?><?php echo set_bool($nursery->active); ?><…

EL表达式, JSTL, 获取map集合中key的value

序言&#xff1a;今天在项目中使用了map存储list和普通对象&#xff0c;但是在jsp中显示的时候出来问题&#xff0c;后经查阅&#xff0c;终于解决&#xff0c;现在记录一下&#xff0c;以便以后查阅&#xff1a; 一&#xff1a;后台代码如下&#xff1a; package cn.gov.csrc…

html选择器是什么,CSS3选择器是什么?

首先我们来看一下displaynone的意思是什么&#xff1f;display:none的意思&#xff1a;隐藏元素并脱离文档&#xff0c;流就是隐藏该区域&#xff0c;不占实际空间&#xff0c;但对后台来说真实存在&#xff0c;可以获取被隐藏的元素简单的来说就是将元素设置为none的时候既不会…

零基础学计算机408,又一所重点大学改考408!21计算机考研会全面408吗?

【北京工业大学】于7月17日发布《关于北京工业大学2021年全国硕士研究生招生考试部分考试科目及考试大纲调整的通知》&#xff0c;要点如下&#xff1a;文法学部0401教育学专业课改考 311统教育学信息学部计算机学院0812计算机科学与技术0839网络空间安全0854电子信息 (专业学位…

国贸专业要考计算机二级,国贸专业考计算机二级有没有必要

类似问题答案我是自动化专业的学生&#xff0c;大一的时候有没有必要考计算机二级证书计算机二级 虽然不是很重要 但是考了也是有好处的 自动化的跟计算机联系非常大 二级证不怎么重要 但是C语言很重要 对于你们 希望你还是去考个二级作为学习建筑类专业的学生,如果考试计算机二…