Linux 网络编程 调试工具
这篇说一下用于网络编程的两个调试工具,netstat和tcpdump
(一)netstat
先看一下手册
NAME
netstat - Print network connections, routing tables, interface statis‐
tics, masquerade connections, and multicast memberships
常见参数
-a (all)显示所有选项,默认不显示LISTEN相关
-t (tcp)仅显示tcp相关选项
-u (udp)仅显示udp相关选项
-n 拒绝显示别名,能显示数字的全部转化成数字。
-l 仅列出有在 Listen (监听) 的服務状态
-p 显示建立相关链接的程序名
-r 显示路由信息,路由表
-e 显示扩展信息,例如uid等
-s 按各个协议进行统计
-c 每隔一个固定时间,执行该netstat命令。
提示:LISTEN和LISTENING的状态只有用-a或者-l才能看到
netstat可以查看网络端点的状态,就好像这样:
找出运行在指定端口的进程
netstat -an | grep ':80'
客户端和服务器正在通信时(客户端的socket 127.0.0.1:42490)
lei@ubuntu:~$ netstat -an | grep ':8080'
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:8080 127.0.0.1:42490 ESTABLISHED
tcp 0 0 127.0.0.1:42490 127.0.0.1:8080 ESTABLISHED
客户端正常退出后
lei@ubuntu:~$ netstat -an | grep ':8080'
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:8080 127.0.0.1:42490 TIME_WAIT
这样就可以方便地观察客户端与服务器的连接状态,知道程序是否有错
(二)tcpdump
DESCRIPTION
Tcpdump prints out a description of the contents of packets on a net‐
work interface that match the boolean expression.
使用tcpdump来抓包(这里我只说抓tcp包的情况)
通常tcpdump对tcp数据包的显示格式如下:
src > dst: flags data-seqno ack window urgent options
src 和 dst 是源和目的IP地址以及相应的端口. flags 标志由S(SYN), F(FIN), P(PUSH, R(RST),
W(ECN CWT(nt | rep:未知, 需补充))或者 E(ECN-Echo(nt | rep:未知, 需补充))组成,
单独一个'.'表示没有flags标识.
监视指定网络接口的数据包
tcpdump -i eth1
如果不指定网卡,默认tcpdump只会监视第一个网络接口,一般是eth0,下面的例子指定网络接口lo。
监视指定主机和端口的数据包
如果想要获取主机端口为8080接收或发出的包,使用如下命令
(sudo是用root的权限运行)
sudo tcpdump -i lo tcp port 8080
(lo是什么呢,使用ifconfig命令可以看到
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:75 errors:0 dropped:0 overruns:0 frame:0
TX packets:75 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:4337 (4.3 KB) TX bytes:4337 (4.3 KB)
)
以下是监视程序在运行时传输数据的情况
(1)建立连接
lei@ubuntu:~$ sudo tcpdump -i lo tcp port 8080
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 96 bytes
19:43:45.788995 IP localhost.45867 > localhost.http-alt: Flags [S], seq 2913516689, win 32792, options [mss 16396,sackOK,TS val 491508 ecr 0,nop,wscale 6], length 0
19:43:45.789017 IP localhost.http-alt > localhost.45867: Flags [S.], seq 2915754001, ack 2913516690, win 32768, options [mss 16396,sackOK,TS val 491508 ecr 491508,nop,wscale 6], length 0
19:43:45.789040 IP localhost.45867 > localhost.http-alt: Flags [.], ack 1, win 513, options [nop,nop,TS val 491508 ecr 491508], length 0
(这是程序运行时客户端与服务器连接时传输的数据,可以看到刚好有三个包,我想就是tcp建立连接时握手要用到的三个包)
(2)传输数据
然后我用客户端给服务器发一个字符串“client”(这里可以看到有localhost.http-alt > localhost.45867的报文,
这是因为tcp的确认重传机制,接收方要发送一个确认报文,同时也可以看到长度为6==“client”的长度)
19:58:45.002150 IP localhost.45867 > localhost.http-alt: Flags [P.], seq 18:24, ack 1, win 513, options [nop,nop,TS val 716312 ecr 716312], length 6
19:58:45.002164 IP localhost.http-alt > localhost.45867: Flags [.], ack 24, win 512, options [nop,nop,TS val 716312 ecr 716312], length 0
然后服务器发回给客户端
19:58:45.002182 IP localhost.http-alt > localhost.45867: Flags [P.], seq 1:7, ack 24, win 512, options [nop,nop,TS val 716312 ecr 716312], length 6
19:58:45.002208 IP localhost.45867 > localhost.http-alt: Flags [.], ack 7, win 513, options [nop,nop,TS val 716312 ecr 716312], length 0
(3)关闭连接
客户端发送退出信息“exit”(这个只是我在程序里面的设定)
20:02:45.854015 IP localhost.45867 > localhost.http-alt: Flags [P.], seq 24:28, ack 7, win 513, options [nop,nop,TS val 776525 ecr 716312], length 4
服务器确认退出,发送“user_exit"(这个只是我在程序里面的设定)
20:02:45.854155 IP localhost.http-alt > localhost.45867: Flags [P.], seq 7:16, ack 28, win 512, options [nop,nop,TS val 776525 ecr 776525], length 9
释放连接(tcp释放连接要用四个报文)
20:02:45.854188 IP localhost.http-alt > localhost.45867: Flags [F.], seq 16, ack 28, win 512, options [nop,nop,TS val 776525 ecr 776525], length 0
20:02:45.854300 IP localhost.45867 > localhost.http-alt: Flags [.], ack 16, win 513, options [nop,nop,TS val 776525 ecr 776525], length 0
20:02:45.854724 IP localhost.45867 > localhost.http-alt: Flags [F.], seq 28, ack 17, win 513, options [nop,nop,TS val 776525 ecr 776525], length 0
20:02:45.854754 IP localhost.http-alt > localhost.45867: Flags [.], ack 29, win 512, options [nop,nop,TS val 776525 ecr 776525], length 0
/*********************
* 新增内容
* 新增日期:2013-12-10
**********************/
tcpdump进阶
最近用到的tcpdump的参数有
-A Print each packet (minus its link level header) in ASCII. Handy for capturing web pages.
-c Exit after receiving count packets.
-x Print each packet (minus its link level header) in hex. The smaller of the entire packet or snaplen bytes will be printed. Note that this is the entire
link-layer packet, so for link layers that pad (e.g. Ethernet), the padding bytes will also be printed when the higher layer packet is shorter than the
required padding.-xx Print each packet, including its link level header, in hex.
另外tcpdump还支持更复杂的指定主机、端口、源、目的地的选项
(1)想要截获所有某主机收到的和发出的所有的数据包:
tcpdump host 210.135.25.46
(2)截获所有某主机+主机某些端口收到的和发出的所有的数据包(以16进制和ascii形式打印出来):
sudo tcpdump -XX host 210.135.25.46 and \(port 48323 or port 58795\)
复杂的条件可以and、or、()的组合表示出来(注意括号前要加上\)
(3)指定发送源、目的端口或ip
使用src、dst关键字
截获所有某主机+主机某些端口发出的所有的数据包
sudo tcpdump host 210.135.25.46 and src port 48323
还有更高级的应用,后面用到会继续补上