传输层毫无疑问是重中之重,工具也很多。我们就按排查场景来介绍工具。
路径可达性测试
如果我们要测试 TCP 握手,我们有 telnet、nc 这两个常规工具。比如 telnet:
telnet
$ telnet www.baidu.com 443
Trying 180.101.49.12...
Connected to www.a.shifen.com.
Escape character is '^]'.
nc
用 nc 呢,可以这样:
$ nc -w 2 -zv www.baidu.com 443
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 112.80.248.75:443.
Ncat: 0 bytes sent, 0 bytes received in 0.02 seconds.
说明
端口号443通常用于运行HTTPS(超文本传输安全协议)服务。HTTPS是一种基于安全套接层/传输层安全(SSL/TLS)的HTTP(超文本传输协议),它提供了加密的数据传输和身份验证功能,以确保数据在客户端和服务器之间的通信安全。
当你在浏览器中访问一个使用HTTPS的网站时,浏览器会默认使用443端口与服务器建立一个安全的连接。通过使用HTTPS,网站可以保护用户的隐私和敏感数据,例如登录凭据、支付信息和个人资料等,防止被窃听、篡改或冒充。
在实际应用中,很多网站都会同时提供HTTP(通常使用80端口)和HTTPS服务,但为了保护用户数据和隐私,越来越多的网站和服务现在默认使用HTTPS。此外,一些现代浏览器和搜索引擎也优先对待支持HTTPS的网站,提高其排名和可信度。
netstat
• 查看当前连接状况
netstat 命令是一个经典命令了,很多同学都会使用它来获取当前的 TCP、UDP 等的连接信息,比如:
$ netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 280 10.0.2.15:22 10.0.2.2:56669 ESTABLISHED
tcp6 0 0 :::22 :::* LISTEN
查看当前连接的传输速率
有时候,你的网络跑得挺繁忙的,但你却不知道哪个连接占用了大量的带宽?你可以用 iftop。这个工具不是系统默认自带的,需要你安装一下,然后执行 iftop 就好了。对了,你需要有 sudo 权限,也就是执行 sudo iftop,然后就能看到不同连接的传输速率,把祸害你带宽的连接给找到。比如下面这样:

查看丢包和乱序等的统计
其实,用 netstat 除了可以获取实时连接状况,还可以获取历史统计信息。比如,你怀疑一台机器的网络很不稳定,除了用 ping 做简单的测试,你还可以用 netstat -s 来获取更加详细的统计信息。比如,其中的 TCP 丢包和乱序计数值,就能帮助你判断传输层的状况。下面是我截取的某一次 netstat -s 命令的输出:
$ watch --diff netstat -s 或者
netstat -s
......
Tcp:
16 active connection openings
1 passive connection openings
8 failed connection attempts
1 connection resets received
1 connections established
6254 segments received
4035 segments sent out
1 segments retransmitted
0 bad segments received
3 resets sent
......
TcpExt:
1 ICMP packets dropped because socket was locked
3 TCP sockets finished time wait in fast timer
8 delayed acks sent
4674 packet headers predicted
10 acknowledgments not containing data payload received
1008 predicted acknowledgments
TCPTimeouts: 1
TCPBacklogCoalesce: 140
1 connections reset due to early user close
TCPRcvCoalesce: 2187
TCPAutoCorking: 110
TCPSynRetrans: 1
TCPOrigDataSent: 1041
TCPDelivered: 1049
当然,上面这个算运维“青铜”版。你也可以写一个简单的脚本,在两次 netstat -s 命令之间执行 sleep,然后计算两个读数之间的差值,并除以 sleep 的时间,得到大致的变化速度。这样就又升级了一点。
如果你想做得再到位一点,你可以把 netstat -s 的输出值写入到 TSDB,然后用 Grafana 之类的 Dashboard 进行展示,这样不仅有视图,也有历史值,可以算运维“王者”了。
还有 ss?
ss 命令是 Iproute2 包里的命令,也是 netstat 的“取代者”。它提供了对 socket 的丰富的统计信息。比如下面这条命令我也经常用,可以查看到当前连接的统计信息:
ss -s
Total: 3068 (kernel 12262)
TCP: 2096 (estab 968, closed 1067, orphaned 0, synrecv 0, timewait 1064/0), ports 0
Transport Total IP IPv6
* 12262 - -
RAW 2 2 0
UDP 62 33 29
TCP 1029 832 197
INET 1093 867 226
FRAG 0 0 0
当然,也不能完全说“ss 等于 netstat”,因为事实上 netstat 命令的功能,被拆分到了 ss 和 ip 这两个命令里,并分别得到了丰富和加强。
这个结果是通过 ss 命令查看 Linux 系统中的网络套接字信息。ss 命令(socket statistics)是一个功能强大的工具,用于获取有关 Linux 系统中套接字的信息。这里的输出显示了网络套接字的统计信息。让我们详细解释这些术语:
- Total: 总套接字数。这里的总数是 3068(内核中的 12262)。
- TCP: 这部分显示了 TCP 协议的套接字信息,包括:
• estab:已建立连接的套接字数(968)。
• closed:已关闭连接的套接字数(1067)。
• orphaned:孤立的套接字数(0)。
• synrecv:等待确认连接请求的套接字数(0)。
• timewait:处于 TIME_WAIT 状态的套接字数(1064)和其子计数(0)。
• ports:占用的端口数量(0)。3. Transport:传输层协议类型。 - Total:每种传输层协议的套接字总数。
- IP:每种传输层协议使用的 IPv4 套接字数。
- IPv6:每种传输层协议使用的 IPv6 套接字数。
对于表格中的其他项,含义如下:
• INET:表示 Internet 协议族(IPv4 和 IPv6)的套接字。这里的总数是 1093(IPv4 的 867 和 IPv6 的 226)。
• FRAG:表示已分片的 IP 数据报。这里的总数是 0(IPv4 和 IPv6 都是 0)。
• RAW:表示原始套接字。原始套接字允许直接访问底层传输协议,绕过常规的网络协议处理。这里的总数是 2(IPv4 的 2 和 IPv6 的 0)。
• UDP:表示使用用户数据报协议(User Datagram Protocol)的套接字。这里的总数是 62(IPv4 的 33 和 IPv6 的 29)。
• TCP:表示使用传输控制协议(Transmission Control Protocol)的套接字。这里的总数是 1029(IPv4 的 832 和 IPv6 的 197)。
这个结果展示了系统上各种网络协议和套接字状态的详细统计信息。
网络套接字(Network Socket)是计算机网络中的一个概念,用于描述操作系统中用于管理网络连接的对象。简单来说,网络套接字就是用于通信的端点,允许程序在网络中发送和接收数据。套接字在应用程序和网络协议栈之间建立了一个抽象层,使得应用程序能够更简便地进行网络通信。
在计算机网络中,通常使用两种主要的套接字类型:TCP(传输控制协议)套接字和 UDP(用户数据报协议)套接字。TCP 套接字提供了一种可靠、面向连接的通信方式,而 UDP 套接字则提供了一种不可靠、无连接的通信方式。
“总套接字数”是指系统中所有类型的网络套接字的数量,包括 TCP、UDP、RAW(原始套接字)以及其他协议族的套接字。在 ss -s 命令的输出中,总套接字数是 3068(内核中的 12262)。这意味着当前系统中有 3068 个网络套接字正在被使用,而内核可能还在处理更多的套接字(12262 个)。
总之,网络套接字是用于管理网络连接的端点,而总套接字数表示当前系统中正在使用的所有类型套接字的数量。
在 C 语言中,可以使用套接字 API(应用程序接口)来创建和管理网络套接字。以下是一个简单的示例,展示了如何使用 C 语言创建一个基于 TCP 的 IPv4 网络套接字:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
int sockfd; // 套接字描述符
struct sockaddr_in server_addr; // 服务器地址结构
// 创建套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
// 配置服务器地址
server_addr.sin_family = AF_INET; // 地址族:IPv4
server_addr.sin_port = htons(8080); // 端口号:8080(网络字节序)
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // IP 地址:127.0.0.1
// 连接服务器
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("connect");
exit(EXIT_FAILURE);
}
// ... 这里可以进行发送和接收数据的操作
// 关闭套接字
close(sockfd);
return 0;
}
这个示例演示了如何创建一个 TCP 套接字,用于连接到一个运行在本地(IP 地址为 127.0.0.1)的服务器,服务器监听的端口号为 8080。首先,程序使用 socket() 函数创建一个套接字,并将其描述符存储在变量 sockfd 中。然后,程序使用 connect() 函数连接到服务器。在实际应用中,你需要在连接成功后添加发送和接收数据的代码。最后,使用 close() 函数关闭套接字。
需要注意的是,这个示例仅展示了客户端的代码。要创建一个完整的网络应用程序,你还需要编写服务器端的代码。服务器端代码将包括创建套接字、绑定套接字到特定的 IP 地址和端口、监听连接请求、接受客户端连接以及发送和接收数据的操作。




