(一),详解linux netstat输出的网络连接状态信息


目录:
一、生产服务器netstat tcp连接状态................................................................................ 2

1.1生产服务器某个业务LVS负载均衡上连接状态数量............................................... 2

1.2生产服务器某个业务web上连接状态数量............................................................ 3

1.3 生产服务器某个业务db上连接状态数量.............................................................. 3

二、tcp连接状态的描述说明(netstat输出)........................................................................ 4

2.1 执行netstat -n查看输出结果共6..................................................................... 4

2.2 通过man netstat查看netstat输出结果信息......................................................... 4

2.3netstat第六列State的状态信息......................................................................... 5

2.4netstat第六列State状态信息转换图表.............................................................. 6

2.4.1 状态参考图一................................................................................................... 7

2.4.2 状态参考图二................................................................................................... 9

2.4.3 状态参考图三................................................................................................. 10

2.4.4 客户端的状态变化描述............................................................................ 10

2.4.5 服务器的状态变化描述............................................................................ 10

2.4.6 其他的状态变化描述总结......................................................................... 11

            更多目录见博文结尾。

一、生产服务器netstat tcp连接状态

1.1生产服务器某个业务LVS负载均衡上连接状态数量

[oldboy@LVS-1-1 ~]$ netstat -n |awk '/^tcp/ {++oldboy[$NF]} END {for(a in oldboy) print a, oldboy[a]}'

TIME_WAIT 9137

CLOSE_WAIT 207

FIN_WAIT1 547

ESTABLISHED 597

FIN_WAIT2 74

SYN_RECV 70

CLOSING 55

LAST_ACK 8

[root@lvs_nginx~]#netstat -n |awk '/^tcp/ {++oldboy[$NF]} END {for(a in oldboy) print a, oldboy[a]}'
TIME_WAIT 422
CLOSE_WAIT 590
FIN_WAIT1 56
FIN_WAIT2 28
ESTABLISHED 1731

1.2生产服务器某个业务web上连接状态数量

[root@web1 ~]# netstat -n |awk '/^tcp/ {++oldboy[$NF]} END {for(a in oldboy) print a, oldboy[a]}'
TIME_WAIT 418
FIN_WAIT1 7
FIN_WAIT2 3
ESTABLISHED 1097
LAST_ACK 2

[root@web2 ~]# netstat -n |awk '/^tcp/ {++oldboy[$NF]} END {for(a in oldboy) print a, oldboy[a]}'
TIME_WAIT 250
FIN_WAIT1 2
FIN_WAIT2 3
ESTABLISHED 1032
LAST_ACK 2

[root@old_web ~]# netstat -n |awk '/^tcp/ {++oldboy[$NF]} END {for(a in oldboy) print a, oldboy[a]}'
TIME_WAIT 342
CLOSE_WAIT 618
FIN_WAIT1 37
FIN_WAIT2 3
ESTABLISHED 1681
SYN_RECV 1

[root@K32_50718 ~]# netstat -n |awk '/^tcp/ {++oldboy[$NF]} END {for(a in oldboy) print a, oldboy[a]}'

TIME_WAIT 4146

FIN_WAIT1 352

FIN_WAIT2 1112

ESTABLISHED 8451

SYN_RECV 186

CLOSING 9

LAST_ACK 102

1.3 生产服务器某个业务db上连接状态数量

[root@web_slave ~]# netstat -n |awk '/^tcp/ {++oldboy[$NF]} END {for(a in oldboy) print a, oldboy[a]}'
TIME_WAIT 263
FIN_WAIT1 1
FIN_WAIT2 48
ESTABLISHED 918

二、tcp连接状态的描述说明(netstat输出)

2.1 执行netstat -n查看输出结果共6

[root@OLDBOY ~]# netstat -n 

Active Internet connections (w/o servers)

Proto Recv-Q Send-Q Local AddressForeign AddressState

tcp00 10.0.0.183:5058410.0.0.181:22ESTABLISHED 

2.2 通过man netstat查看netstat输出结果信息

[root@oldboy ~]# man netstat 

OUTPUT

Active Internet connections (TCP, UDP, raw)

Proto

The protocol (tcp, udp, raw) used by the socket.

第一列为socket使用的协议。

Recv-Q

The count of bytes not copied by the user program connected to this socket.

第二列为接到的但是还没处理的字节数。

Send-Q

The count of bytes not acknowledged by the remote host.

第三列为已经发送的但是没有被远程主机确认收到的字节数。

Local Address

Address and port number of the local end of the socket.Unless the --numeric(-n)

optionisspecified,thesocketaddress is resolved to its canonical host name

(FQDN), and the port number is translated into the corresponding service name.

第四列为 本地的地址及端口。

Foreign Address

Address and port number of the remote endofthesocket.Analogousto"Local Address."

第五列为外部的地址及端口。

State

Thestateofthesocket.Sincethere are no states in raw mode and usually no

states used in UDP, this column may be left blank. Normally this can be one of sev-

eral values:

第六列为socket的状态,通常仅仅有tcp的状态,状态值可能有ESTABLISHED,SYN_SENT,SYN_RECV FIN_WAIT1,FIN_WAIT2,TIME_WAIT等,详见下文。其中,最重要的是第六列。

2.3 netstat第六列State的状态信息

如果我们执行man netstat可以找到如下的帮助信息

State

Thestateofthesocket.Sincethere are no states in raw mode and usually no

states used in UDP, this column may be left blank. Normally this can be one of sev-

eral values:

第六列为socket的状态,通常仅仅有tcp的状态,状态值可能有ESTABLISHED,SYN_SENT,SYN_RECV FIN_WAIT1,FIN_WAIT2,TIME_WAIT等,详见下文。其中,最重要的是第六列。

ESTABLISHED

The socket has an established connection.

socket已经建立连接,表示处于连接的状态,一般认为有一个ESTABLISHED认为是一个服务的并发连接。这个连接状态在生产场景很重要,要重点关注。

SYN_SENT

The socket is actively attempting to establish a connection. 

socket正在积极尝试建立一个连接,即处于发送后连接前的一个等待但未匹配进入连接的状态。

SYN_RECV

A connection request has been received from the network.

已经从网络上收到一个连接请求。

FIN_WAIT1

The socket is closed, and the connection is shutting down. 

socket已关闭,连接正在或正要关闭。

FIN_WAIT2

Connectionisclosed,andthesocket is waiting for a shutdown from the remote end.

连接已关闭,并且socket正在等待远端结束。

TIME_WAIT

The socket is waiting after close to handle packets still in the network.

socket正在等待关闭处理仍在网络上的数据包,这个连接状态在生产场景很重要,要重点关注。

CLOSED The socket is not being used.| socket不在被占用了。

CLOSE_WAIT

The remote end has shutdown, waiting for the socket to close.

远端已经结束,等待socket关闭。

LAST_ACK

The remote end has shut down, and the socket is closed. Waiting for acknowl-edgement.|

远端已经结束,并且socket也已关闭,等待acknowl-edgement。

LISTEN Thesocketislisteningforincoming connections.Such sockets are not

included in the output unless you specify the --listening (-l) or --all (-a)

option.

socket正在监听连接请求。

CLOSING

Both sockets are shut down but we still don’t have all our data sent.

sockets关闭,但是我们仍旧没有发送数据。

UNKNOWN

The state of the socket is unknown

未知的状态。

2.4 netstat第六列State状态信息转换图表

TCP的状态图,这是一个看起来比较复杂的状态迁移图,因为它包含了两个部分---服务器的状态迁移和客户端的状态迁移,如果从某一个角度出发来看这个图,就会清晰许多,这里面的服务器和客户端都不是绝对的,发送数据的就是客户端,接受数据的就是服务器。

2.4.1 状态参考图一
见后续博文

2.4.2 状态参考图二

见后续博文

2.4.3 状态参考图三

见后续博文

2.4.4 客户端的状态变化描述

通过状态参考图三,客户端的状态可以用如下的流程来表示:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
以上流程是在程序正常的情况下应该有的流程,在建立连接时,当客户端收到SYN报文的ACK以后,客户端就打开了数据交互地连接。而结束连接则通常是客户端主动结束的,客户端结束应用程序以后,需要经历FIN_WAIT_1,FIN_WAIT_2等状态,这些状态的迁移就是前面提到的结束连接的四次握手。

2.4.5 服务器的状态变化描述

通过状态参考图三,服务器的状态可以用如下的流程来表示:
CLOSED->LISTEN->SYN_RECVD->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
在建立连接的时候,服务器端是在第三次握手之后才进入数据交互状态,而关闭连接则是在关闭连接的第二次握手以后(注意不是第四次)。而关闭以后还要等待客户端给出最后的ACK包才能进入初始的状态。

2.4.6 其他的状态变化描述总结

针对服务器和客户端两方面的总结如下

1)LISTEN->SYN_SENT,对于这个解释就很简单了,服务器有时候也要打开连接的嘛。

2)SYN_SENT->SYN_RECVD,服务器和客户端在SYN_SENT状态下如果收到SYN数据报,则都会发送SYN的ACK数据报并把自身状态调整到SYN_RECVD,准备进入ESTABLISHED 

3)SYN_SENT->CLOSED,在发送超时的情况下,会返回到CLOSED状态。

4)SYN_RECVD->LISTEN,如果受到RST包,会返回到LISTEN状态。

5)SYN_RECVD->FIN_WAIT_1,这个迁移是说,可以不用到ESTABLISHED状态,而可以直接跳转到FIN_WAIT_1状态并等待关闭。


(二)庖丁解牛获取连接状态数的命令

三、庖丁解牛获取连接状态数的命令
3.1 获取连接状态数的awk命令

netstat -n |awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

提示:将netstat -n的结果通过管道符交给awk命令处理。
3.2先来执行下netstat -n

[oldboy@LVS-1-1 ~]$ netstat -n|more #截取部分有代表性的内容如下

Active Internet connections (w/o servers)

Proto Recv-Q Send-Q Local AddressForeign AddressState

tcp00 124.123.3.79:80219.85.194.23:12004SYN_RECV

tcp00 124.123.3.77:80183.8.74.57:3276SYN_RECV

tcp00 124.123.3.77:80124.236.0.214:63191SYN_RECV

tcp00 124.123.3.77:80221.237.233.41:2338TIME_WAIT

tcp01023 124.123.3.77:8061.178.184.222:62683FIN_WAIT1

tcp00 124.123.3.77:80222.79.242.74:7416TIME_WAIT

tcp04839 124.123.3.77:80121.31.42.148:30638FIN_WAIT1

tcp00 124.123.3.77:80183.10.154.60:37282TIME_WAIT

tcp01 124.123.3.77:8059.49.174.176:26913CLOSING

tcp00 124.123.3.77:80120.87.129.35:1787TIME_WAIT

tcp0174 124.123.3.77:80120.71.134.66:1165CLOSING

提示:实际执行这条命令的时候,可能会得到上万条类似的记录,我们只取若干来举例。

3.3拆解awk命令

1)完整命令如下

netstat -n |awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

2awk庖丁解牛

命令拆分

功能说明

/^tcp/

过滤出以tcp开头的行,“^”为正则表达式用法,以...开头,这里是过滤出以tcp开头的行。

S[]

定义了一个名叫S的数组,在awk中,数组下标通常从 1 开始,而不是 0

NF

当前记录里域个数,默认以空格分隔,如上所示的记录,NF域个数等于6

$NF

表示一行的最后一个域的值,如上所示的记录,$NF也就是$6,表示第6个字段的值,也就是SYN_RECVTIME_WAIT等。

S[$NF]

表示数组元素的值,如上所示的记录,就是S[TIME_WAIT]状态的连接数

++S[$NF]

表示把某个数加一,如上所示的记录,就是把S[TIME_WAIT]状态的连接数加一

END


for(key in S)

遍历S[]数组

print key,”\t”,S[key]

打印数组的键和值,中间用\t制表符分割,显示好一些。

3)举个小例子练手

已知test.txt内容:

001 name wodi12k

002 name yingsui 15k

003 name jeacen10k

004 name kuqi8k

005 name yideng10k

006 name xiaofan8k

要求:统计老男孩培训学生中,不同薪水的学生的数量报表。

[oldboy@test ~]$ cat test.txt |awk '/^00/ {++S[$NF]} END {for (a in S) print a,S[a]}'

15k 1

8k 2

10k 2

12k 1

提示:模拟前面的awk命令,过滤以00开头的行,然后进行处理。

上述awk数组元素内容:

key=12k S[12K]=1

key=15k S[15K]=1

key=10k S[10K]=2

key=8kS[8K]=2

[oldboy@test ~]$ awk '/^00/ {++S[$NF]} END {for (a in S) print a,S[a]}' test.txt

15k 1

8k 2

10k 2

12k 1

提示:awk可以直接处理文本,因此,不需要去cat,不但不专业,而且内容多时,影响处理效率。


(三)awk数组命令经典生产实战应用拓展

四、awk数组命令生产实战拓展
4.1统计apache日志单ip访问请求数排名(这个常用,考试也常考)

假设apache日志内容access.log内容为:

10.0.0.41 - - [03/Dec/2010:23:27:01 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -

10.0.0.43 - - [03/Dec/2010:23:27:01 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -

10.0.0.42 - - [03/Dec/2010:23:27:01 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -

10.0.0.46 - - [03/Dec/2010:23:27:02 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -

10.0.0.42 - - [03/Dec/2010:23:27:02 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -

10.0.0.47 - - [03/Dec/2010:23:27:02 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -

10.0.0.41 - - [03/Dec/2010:23:27:02 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -

10.0.0.47 - - [03/Dec/2010:23:27:02 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -

10.0.0.41 - - [03/Dec/2010:23:27:03 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -

10.0.0.46 - - [03/Dec/2010:23:27:03 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -

4.1.1 给出3种解决方案

法一:

[root@oldboy /]# awk '{++S[$1]} END {for (oldboy in S) print oldboy ,S[oldboy]}' access.log |sort -rn -k2

10.0.0.41 3

10.0.0.47 2

10.0.0.46 2

10.0.0.42 2

10.0.0.43 1

#提示 $1为第一个域的内容。-k2 为对第二个字段排序,即对数量排序。

2

[root@oldboy /]# awk '{print $1}' access.log|sort|uniq -c |sort -rn -k1

3 10.0.0.41

2 10.0.0.47

2 10.0.0.46

2 10.0.0.42

1 10.0.0.43

提示:这个方法是容易想到的简单易用的方法,对于大多数同学来说,此法其实更适合大家,awk数组的方法看起来好,实际上对于初级运维来来说有点难度,经常记不住。

3

[root@oldboy /]# sed's/- -.*$//g' access.log|sort|uniq -c|sort -rn -k1

3 10.0.0.41 

2 10.0.0.47 

2 10.0.0.46 

2 10.0.0.42 

1 10.0.0.43 

提示:sed管道后的第一个sort是让所有一样的IP挨着,因为uniq -c只能对相邻的IP行去重计数。

此题的解答可以有10几种,前面的课程我们已经带大家细讲了,这里就不一一讲解了。

4.1.2统计apache日志单ip访问请求数排名价值何在?

解答:通过前面的命令,我们可以找到什么IP的访问apache比较频繁,一般单个IP访问数量过百,就值得怀疑了,如果短时间内上万PV访问,说明就不正常了,可以采取相应的处理手段,比如封掉此IP,此法要慎重,否则,可能会有误封问题,因为,国内的大多数公司还是NAT上网的,出口一个IP

4.2 统计服务器当前单IP连接数最大的IP地址前十

提示:这个命令可以查出遭受DOS攻击的客户端IP地址。待处理内容如下:

netstat -n >test.log的结果:

Active Internet connections (w/o servers)

Proto Recv-Q Send-Q Local AddressForeign AddressState

tcp00 124.123.3.79:80219.85.194.23:12004SYN_RECV

tcp00 124.123.3.77:80183.8.74.57:3276SYN_RECV

tcp00 124.123.3.77:80124.236.0.214:63191SYN_RECV

tcp00 124.123.3.77:80121.31.42.148:2338TIME_WAIT

tcp01023 124.123.3.77:8061.178.184.222:62683FIN_WAIT1

tcp00 124.123.3.77:80222.79.242.74:7416TIME_WAIT

tcp04839 124.123.3.77:80121.31.42.148:30638FIN_WAIT1

tcp00 124.123.3.77:80183.10.154.60:37282TIME_WAIT

tcp01 124.123.3.77:8059.49.174.176:26913CLOSING

tcp00 124.123.3.77:80121.31.42.148:1787TIME_WAIT

tcp0174 124.123.3.77:80183.8.74.57:1165CLOSING

4.2.1 问题解决方案

[root@OLDBOY ~]# awk-F '[ :]+' '{++S[$6]} END {for (a in S) print a ,S[a]}' test.log |sort -rn -k2

121.31.42.148 3

183.8.74.57 2

Foreign 1

61.178.184.222 1

59.49.174.176 1

222.79.242.74 1

219.85.194.23 1

183.10.154.60 1

124.236.0.214 1

提示:

1)结果中的字符等,你可以进一步过滤。

2) 对于多分隔符匹配的用法大家可以参考老男孩的博文

深入浅出三剑客之awk必杀技一例

http://oldboy.blog.51cto.com/2561410/950730

3)实际生产中,我们过滤出已经建立连接的状态ESTABLISHED,然后,应用上述命令处理,完整命令可能为:

netstat -an|awk-F '[ :]+' '{++S[$6]} END {for (a in S) print a ,S[a]}'|sort -rn -k2

4.2.2 生产环境案例

[leo@LVS-1-1 ~]$ netstat -an|grep EST|awk '{print $5}'|cut -d : -f 1|grep -v "^$"|awk '{++ETT[$1]} END {for (oldboy in ETT) print "ip:"oldboy "-----",ETT[oldboy] ''}'|sort -rn -k2|head -10

ip:220.181.125.69----- 51

ip:121.9.222.164----- 38

ip:121.9.222.158----- 38

ip:121.9.222.156----- 38

ip:121.9.222.161----- 36

ip:121.9.222.160----- 32

ip:121.9.222.159----- 32

ip:121.9.222.162----- 31

ip:61.163.7.200----- 29

ip:115.193.163.61----- 27

提示:这是早期的命令案例,我们看到命令虽然很简单,但是搞的很复杂。实际上可以用下面看起来简单,但是难度很大的命令替代之。

netstat -an|grep EST|awk-F '[ :]+' '{++S[$6]} END {for (key in S) print "ip:"key"----->",S[key]}'|sort -rn -k2

注意,这里过滤的是已经建立连接的的连接,即状态ESTABLISHED。

4.2.3 本案例解决的生产问题

netstat -an|grep EST|awk-F '[ :]+' '{++S[$6]} END {for (key in S) print "ip:"key"----->",S[key]}'|sort -rn -k2

注意,这里过滤的是已经建立连接的的连接,即状态ESTABLISHED。

对于命令结果中,单IP结尾的数大的,可以认为是不正常的访问。如 121.31.42.148 100 ,表示一个IP100个连接

一般来说可以怀疑不正常,当网站压力大时,可以考虑限制或封掉这些冒似非法IP,当然,也不排除,企业里多个用户用一个出口IP访问。

壮士扼腕,有时也是必须的,否则,可能网站整体影响更大,甚至瘫痪。有时,各种搜索引擎的爬虫是很疯狂的,通过本例及上面的案例,我们可以再负载IO高时,能够进行临时应对,当然,这不是长久的方法,优化网络和服务器,部署大规模集群服务器才是较好的解决之道。

4.2.4 IDC机房带宽突然暴涨问题经典案例

http://oldboy.blog.51cto.com/2561410/909696


(四)老男孩培训第八节课前awk考试题案例(门户面试题解答)

4.3 老男孩培训第八节课前考试题案例(门户面试题)

考试题七:处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)

oldboy.log

http://www.etiantian.org/index.html

http://www.etiantian.org/1.html

http://post.etiantian.org/index.html

http://mp3.etiantian.org/index.html

http://www.etiantian.org/3.html

http://post.etiantian.org/2.html

解答:

分析:此类问题是运维工作中最常见的问题。可以演变成分析日志,查看TCP各个状态连接数,查看单IP连接数排名等等

第一类过滤域名方法

方法很多老男孩这里给出六种为例。还可以写出几种留给大家了。

法一:

[root@oldboy ~]# cut -d "/" -f 3 oldboy.log |sort|uniq -c

1 mp3.etiantian.org

2 post.etiantian.org

3 www.etiantian.org

法二:

[root@oldboy ~]# awk -F "/" '{print $3}' oldboy.log |sort|uniq -c

1 mp3.etiantian.org

2 post.etiantian.org

3 www.etiantian.org

法三:

[root@oldboy ~]# sed 's/^ htt.*\/\///g' oldboy.log |sed 's/\/.*html$//g'|sort|uniq -c

1 mp3.etiantian.org

2 post.etiantian.org

3 www.etiantian.org

法四:

[root@oldboy ~]# cat oldboy.log |tr "\/" "\n"|grep etiantian|sort|uniq -c

1 mp3.etiantian.org

2 post.etiantian.org

3 www.etiantian.org

法五:set+完全正则匹配

[root@OLDBOY ~]# sed -e 's#^.*//\(.*etiantian.*\)/.*html#\1#gp' oldboy.log|sort|uniq -c|sort -rn

6 www.etiantian.org

4 post.etiantian.org

2 mp3.etiantian.org

第二类:awk数组

法五:

[root@oldboy ~]#cut -d "/" -f 3 test.log|awk '{++S[$1]} END {for(key in S) print key,S[key]}'|sort -k2

mp3.etiantian.org 1

post.etiantian.org 2

www.etiantian.org 3

法六:一个利用AWK数组综合解决方法

[root@oldboy ~]# awk -F "/" '{++S[$3]} END {for(key in S) print key,S[key]}' oldboy.log|sort -k2

mp3.etiantian.org 1

post.etiantian.org 2

www.etiantian.org 3

以上答案不同组合已可以达到10多种答案


(五)linux生产服务器有关网络状态的优化措施

5.1高并发linux生产服务器内核参数优化案例

高并发linux生产服务器内核参数优化案例

说明:本优化适合apache,nginx,squid多种等web应用,特殊的业务也可能需要略作调整。

所谓内核优化,主要是在Linux系统中针对业务服务应用而进行的系统内核参数优化,优化并无特殊的标准,下面以常见生产环境linux的内核优化为例讲解,仅供大家参考:

net.ipv4.tcp_fin_timeout = 2

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_tw_recycle = 1

net.ipv4.tcp_syncookies = 1

net.ipv4.tcp_keepalive_time = 600

net.ipv4.ip_local_port_range = 400065000

net.ipv4.tcp_max_syn_backlog = 16384

net.ipv4.tcp_max_tw_buckets = 36000

net.ipv4.route.gc_timeout = 100

net.ipv4.tcp_syn_retries = 1

net.ipv4.tcp_synack_retries = 1

net.core.somaxconn = 16384

net.core.netdev_max_backlog = 16384

net.ipv4.tcp_max_orphans = 16384

#以下参数是对iptables防火墙的优化,防火墙不开会提示,可以忽略不理。

net.ipv4.ip_conntrack_max = 25000000

net.ipv4.netfilter.ip_conntrack_max=25000000

net.ipv4.netfilter.ip_conntrack_tcp_timeout_established=180

net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait=120

net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait=60

net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait=120

将上面的内核参数值加入/etc/sysctl.conf文件中,然后执行如下命令使之生效:sysctl -p 

参数解释找谷歌吧,大把大把。呵呵。

六、TCP 连接状态

6.1三次握手建立连接

TCP是一个面向连接的协议,所以在连接双方发送数据之前,都需要首先建立一条连接。TCP连接的建立可以简单的称为三次握手,而连接的中止则可以叫做四次握手
1.连接的建立
在建立连接的时候,客户端首先向服务器申请打开某一个端口(用SYN段等于1的TCP报文),然后服务器端发回一个ACK报文通知客户端请求报文收到,客户端收到确认报文以后再次发出确认报文确认刚才服务器端发出的确认报文(绕口么),至此,连接的建立完成。这就叫做三次握手。如果打算让双方都做好准备的话,一定要发送三次报文,而且只需要三次报文就可以了。如果再加上TCP的超时重传机制,那么TCP就完全可以保证一个数据包被送到目的地。

1)客户端发送 SYN 消息,其中包含服务器的端口和客户端的初始序列号(ISN)到服务器(活动打开)。

2)服务器会发送回SYNACK(其中包括的客户端的 ISN + 1)。

3)客户端发送一个 ACK,(其中包括的服务器的 ISN + 1)。

6.2四次挥手关闭连接

结束连接
TCP有一个特别的概念叫做half-close,这个概念是说,TCP的连接是全双工(可以同时发送和接收)连接,因此在关闭连接的时候,必须关闭传和送两个方向上的连接。客户机给服务器一个FIN为1的TCP报文,然后服务器返回给客户端一个确认ACK报文,并且发送一个FIN报文,当客户机回复ACK报文后(四次握手),连接就结束了。

1)客户端发送一个FIN(活动收盘)。这是一个现在半关闭连接。客户端不能再将数据发送,但仍然能够从服务器接收数据。收到此 FIN 服务器进入被动关闭状态。

2)服务器发送一个ACK(这时客户端 FIN 序列 + 1

3)服务器发送其自身FIN

4)客户端发送一个ACK(这是服务器的 FIN 序列 + 1)。收到此 ACK 服务器关闭连接。

6.3 win32 Netstat 输出说明

状态说明,Netstat 中所示:

状态说明
------------ --------------------------------------------------------
SYN_SEND 指示活动打开。
SYN_RECEIVED 服务器只接收来自客户端的 SYN。
建立的客户端接收到服务器的 SYN 和建立会话。

侦听服务器已准备好接受连接。

注: 请参阅文档 listen() 套接字调用。TCP 套接字侦听状态中的不会显示-这是 NETSTAT 的限制。有关其他信息,请参阅 Microsoft 知识库中相应的文章:

134404NETSTAT。EXE 不显示 TCP 侦听套接字

FIN_WAIT_1 指示活动结束标记。

TIMED_WAIT 客户端活动关闭后将进入此状态。

CLOSE_WAIT 指示被动关闭。服务器只是从客户端接收到第一个 FIN。

FIN_WAIT_2 客户端只是从服务器接收其第一个 FIN 的确认。

当它发送自己 FIN LAST_ACK 服务器处于此状态。

已关闭的服务器从客户端收到 ACK 并关闭连接。

例如,请考虑以下情形:

套接字应用程序已终止,但 Netstat 报告套接字处于 CLOSE_WAIT 状态。这可能表明客户端正确关闭 (已发送 FIN) 的连接,但服务器仍有打开的套接字。这可能是一个实例(在所有线程或进程) 未关闭套接字的结果。

注: 很正常很长的一段时间内处于 TIME_WAIT 状态有一个套接字。指定的时间是在 RFC793 中作为两次最大段生存期 (MSL)。MSL 被指定为 2 分钟。因此,套接字可能处于 TIME_WAIT 状态长 4 分钟。某些系统为 MSL 实施不同的值 (不超过 2 分钟)。

来自http://support.microsoft.com/kb/137984/zh-cn



Logo

更多推荐