网络编程简介(OSI七层协议,TCP协议原理,三次握手与四次挥手)

网络编程

软件开发架构

软件开发架构分为两种:
​ C/S架构
​ B/S架构

C/S架构

​ 客户端与服务器端架构,这种架构也是从用户层面(也可以是物理层面)来划分的。

C/S架构:
Client: 客户端
Server: 服务端
优点:
软件的使用稳定,并且可以节省网络资源。
缺点:
1.若用户想在同一个设备上使用多个软件,必须下载多个客户端。
2.软件的每一次更新,客户端也必须跟着重新下载更新。
C/S架构的软件:
例如: 电脑上的QQ、Pycharm等...手机端(移动端)的微信、王者荣耀等...
 c:客户端:一般泛指客户端应用程序exe,程序需要先安装后,才能运行在用户的电脑上,对用户的电 脑操作系统环境依赖较大。

img
s:服务端:只要访问服务端就会不间断的给我们返回数据。

B/S架构

​ 浏览器端与服务器端架构,这种架构是从用户层面来划分的。

Browser: 浏览器(客户端)
Server: 服务端
优点:
以浏览器充当客户端,无需用户下载多个软件,也无需用户下载更新软件版本,
直接在浏览器上访问需要使用的软件。

缺点:
消耗网络资源过大,当网络不稳定时,软件的使用也会不稳定。
  b:浏览器:其实也是一种Client客户端,只是这个客户端不需要大家去安装什么应用程序,只需在浏览器上通过HTTP请求服务器端相关的资源(网页资源),客户端Browser浏览器就能进行增删改查;
s:服务器:用户通过浏览器上的HTTP请求服务器的相关资源,服务器经过某些处理,匹配给用户指定的数据。

img

手机端c/s看上去很流行,但实际上b/s正在崛起,现在很多主流软件,比如微信、支付宝、QQ等手机端应用程序中添加了很多其他的服务功能,这里只给了一个连接上服务器的链接,用户不需要再重新下载对应的软件使用相应功能,而这些服务链接都是基于b/s架构的。

网络编程的发展史

任何现进的技术最早都来源于军事。军用以后淘汰到民用;

早期打电话需要电话线,电脑需要网线,笔记本电脑、无线电话需要网卡,所以想要实现远程通信第一个需要具备的条件是:物理连接介质。

人要想实现无障碍交流必须说统一的语言 >>> 英文
计算机与计算机之间要想实现远程通信除了有物理连接介质之外还需要
有一套公共的标准/协议。
这种协议称为OSI(open system interconection),七层协议,或者OSI五层协议

互联网协议

互联网协议按照功能不同分为osi七层或tcp/ip五层或tcp/ip四层

OSI七层协议:应用层、表示层、会话层、传输层、网络层、数据链路层、物理连接层
OSI五层协议:应用层、传输层、网络层、数据链路层、物理连接层。

每层运行常见物理设备

OSI七层协议数据传输的封包与解包过程

1.物理连接层

基于电信号传输010101001010二进制数据

2.数据链路层

数据链路层的 "以太网协议",专门用于处理基于电信号发送二进制的数据。

1)规定的电信号的分组方式;
2)规定了任何一台接入互联网的计算机都必须有一块网卡,每一块网卡上面都刻有世界上独一无二的编号;
以上两点合称为’以太网协议‘

网卡:12位16进制数表示,前6位是厂商编号,后6位是流水线编号,我们管这12数叫mac地址。
基于以太网协议(在局域网内部):
广播:在局域网内每个人都向所有进行广播,会产生广播风暴;
单播:只有一个人对所有人进行发送;

交换机:基于以太网协议通信, 可以让多台电脑连接到一起,不能跨局域网通信

img

互联网是有n多个局域网彼此之间连接而成的

img

想要跨局域网进行通信,就到了网络层(互联网)

3.网络层

IP协议
规定了只要是接入互联网的计算机都必须有一个IP地址
ip地址特点:点分十进制
最小:0.0.0.0
最大:255.255.255.255
ip地址目前有两个版本:IPV4 IPV6(由于IPV4已经不够表示目前存在的计算机了 所以推出了IPV6版本)
本机IP: 回环地址 127.0.0.1 ---> localhost
IP地址是动态分配的

4.传输层

TCP\UDP协议,都是基于端口工作的协议
端口(port) :用来唯一标识一台计算机上的某个应用程序
端口号的范围:0~65535
计算机与计算机之间的通信其实是计算机上的应用程序与应用程序之间的通信

注意:0~1024这些都是操作系统默认使用的端口号
建议:使用8000之后的端口
MySQL默认端口:3306
Redis默认端口:6379
django默认端口:8000
flask默认端口:5000
mongodb: 27017
Tomcat: 8080

端口号是动态分配的
第一次起qq分配到的是8989
将qq关闭再次启动端口号可能就变了

.总结
ip地址:用来唯一标识接入互联网的一台计算机
port端口:用来唯一标识一台计算机上的某个应用程序
ip+port:唯一标识接入互联网一台计算机上的某个应用程序

若想服务端与客户端进行通信,必须要建立连接,产生双向通道。
一条是客户端往服务端发送消息的。
另一条是服务端往客户端发送消息的。

5.应用层

HTTP协议(其后家S表示经过美国某机构认证)
FTP协议:流式协议,可靠协议,基于TCP协议通信 必选先建立双向通道

三次握手四次挥手

三次握手建链接

1) 建立双向通道,建立好连接。
2)listen: 监听
3)established: 确认请求建立连接

基于TCP协议的客户端向服务端发送请求,建立一个通道,用于标识请求,服务端确认并接收到请求,向客户端回复也是唯一标识,这时客户端和服务端的单向通道就建立好了,然后服务端向客户端也发送了请求,客户端接受之后,并再次回复服务端,之后服务端到客户端的通道就建立好了由于服务端第一次接受请求与再次向客户端发送请求是同时建立的,两次乐意合并成一次,所以称为三次握手。

img

数据传输

发送数据:
1)write
2)read
客户端往服务端发送数据,数据存放在内存中,需要服务端确认收到,数据才会在内存中释放掉。

img

四次挥手断连接

TIME_WAIT: 时间等待

在客户端和服务端不在进行数据交互时,双方均可断开请求,以客户端为例,如果客户端向服务端发送断开请求,服务端回复客户端确认,此时,客户端到服务端的通道断开了,而服务端还需要一定的延迟,判断是否当时还有数据正在传输,如果有,服务端会发送数据直到完毕,然后向客户端发送断开请求,客户端回应,自此服务端与客户端之间的通道断开,两者通信结束。

img

TCP协议传输数据可靠的原因

TCP协议传输数据之所以可靠是因为两者基于双向通道发消息,只有当收方确认收到消息并反馈发方,才删除内存中数据,如果没有反馈发方,在一定时间内,发方会每隔一段时间向收方发送一次,直到确认收方收到消息。否则,超过一定时间,发方认为收方宕机或其他故障,删除内存中存储的数据,不会再发。

ss命令和netstat命令比较

在早期运维工作中,查看服务器连接数一般都会用netstat命令。其实,有一个命令比netstat更高效,那就是ss(Socket Statistics)命令!
ss命令可以用来获取socket统计信息,它可以显示和netstat类似的内容。
ss的优势在于它能够显示更多更详细的有关TCP和连接状态的信息,而且比netstat更快速更高效。原因如下:
1)当服务器的socket连接数量变得非常大时,无论是使用netstat命令还是直接cat /proc/net/tcp,执行速度都会很慢。可能你不会有切身的感受,但请相信我,当服务器维持的连接达到上万个的时候,使用netstat等于浪费 生命,而用ss才是节省时间。
2)而ss快的秘诀在于它利用到了TCP协议栈中tcp_diag。tcp_diag是一个用于分析统计的模块,可以获得Linux内核中第一手的信息,这就确保了ss的快捷高效。当然,如果你的系统中没有tcp_diag,ss也可以正常运行,只是效率会变得稍慢(但仍然比 netstat要快)。

为了验证ss比netstat更快更高效,可以如下做几个实验看看效果:
几乎所有的Linux系统都会默认包含netstat命令,但并非所有系统都会默认包含ss命令。
netstat命令是net-tools工具集中的一员,这个工具一般linux系统会默认安装的;ss命令是iproute工具集中的一员;
net-tools是一套标准的Unix网络工具,用于配置网络接口、设置路由表信息、管理ARP表、显示和统计各类网络信息等等,但是遗憾的是,这个工具自2001年起便不再更新和维护了。
iproute,这是一套可以支持IPv4/IPv6网络的用于管理TCP/UDP/IP网络的工具集

如果没有ss命令,可以如下安装:
[root@wang ~]# yum install iproute iproute-doc

当服务器维持30000个socket连接时,使用netstat和ss命令统计连接数的耗时情况如下:
[root@wang ~]# netstat -at | wc -l //耗时15.60秒
[root@wang ~]# ss -atr | wc -l //耗时5.40秒(未利用tcp_diag)
[root@wang ~]# ss -atr | wc -l //耗时0.47秒(利用tcp_diag)

ss -a 查看机器的socket连接数
ss -l 查看机器的端口情况
ss -s 查看机器的网络连接数

1)查看当前服务器的网络连接统计。
在服务器产生大量sockets连接时,一般常会使用这个命令做宏观统计。

[root@wang ~]# ss -s
Total: 318 (kernel 419)
TCP:   62 (estab 16, closed 18, orphaned 0, synrecv 0, timewait 17/0), ports 198
 
Transport Total     IP        IPv6
*     419            -         -       
RAW   0         0         0       
UDP   18        18        0       
TCP   44        44        0       
INET      62        62        0       
FRAG      0         0         0
2)查看所有打开的网络端口
如果使用-pl参数的话,则会列出具体的程序名称
[root@wang ~]# ss -l
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:rquotad *:*
LISTEN 0 128 *:46700 *:*
LISTEN 0 100 *:sun-as-jmxrmi *:*
LISTEN 0 128 *:40591 *:*
LISTEN 0 128 *:sunrpc *:*
LISTEN 0 128 *:webcache *:*
........
3)想查看这台服务器上所有的socket连接
如果只想查看TCP sockets,那么使用-ta选项;
如果只想查看UDP sockets,那么使用-ua选项;
如果只想查看RAW sockets,那么使用-wa选项;
如果只想查看UNIX sockets,那么使用-xa选项。
[root@wang ~]# ss -a
......
ESTAB 0 0 101.201.114.106:54957 111.205.224.15:https
TIME-WAIT 0 0 10.25.91.53:58645 10.44.183.73:11212
TIME-WAIT 0 0 10.25.91.53:35920 10.171.60.171:11212
TIME-WAIT 0 0 10.25.91.53:http 100.109.192.96:17837
ESTAB 0 0 101.201.114.106:57479 139.196.38.174:56516
TIME-WAIT 0 0 127.0.0.1:cslistener 127.0.0.1:42728

--------------------------netstat中的各种状态------------------------------

CLOSED         初始(无连接)状态。
LISTEN         侦听状态,等待远程机器的连接请求。
SYN_SEND       在TCP三次握手期间,主动连接端发送了SYN包后,进入SYN_SEND状态,等待对方的ACK包。
SYN_RECV       在TCP三次握手期间,主动连接端收到SYN包后,进入SYN_RECV状态。
ESTABLISHED    完成TCP三次握手后,主动连接端进入ESTABLISHED状态。此时,TCP连接已经建立,可以进行通信。
FIN_WAIT_1     在TCP四次挥手时,主动关闭端发送FIN包后,进入FIN_WAIT_1状态。
FIN_WAIT_2     在TCP四次挥手时,主动关闭端收到ACK包后,进入FIN_WAIT_2状态。
TIME_WAIT      在TCP四次挥手时,主动关闭端发送了ACK包之后,进入TIME_WAIT状态,等待最多MSL时间,让被动关闭端收到ACK包。
CLOSING        在TCP四次挥手期间,主动关闭端发送了FIN包后,没有收到对应的ACK包,却收到对方的FIN包,此时,进入CLOSING状态。
CLOSE_WAIT     在TCP四次挥手期间,被动关闭端收到FIN包后,进入CLOSE_WAIT状态。
LAST_ACK       在TCP四次挥手时,被动关闭端发送FIN包后,进入LAST_ACK状态,等待对方的ACK包。
 
主动连接端可能的状态有:    CLOSED        SYN_SEND        ESTABLISHED
主动关闭端可能的状态有:    FIN_WAIT_1    FIN_WAIT_2      TIME_WAIT
被动连接端可能的状态有:    LISTEN        SYN_RECV        ESTABLISHED
被动关闭端可能的状态有:    CLOSE_WAIT    LAST_ACK        CLOSED


在Linux下,如果连接数比较大,可以使用效率更高的ss来替代netstat。
查看tomcat的并发数:netstat -an|grep 10050|awk '{count[$6]++} END{for (i in count) print(i,count[i])}'

TCP窗口大小为64K是什么意思啊?

TCP协议在能够发送数据之前就建立起了“连接”。要实现这个连接,启动TCP连接的那一方首先将发送一个SYN数据包。这只是一个不包含数据的数据包, 然后,打开SYN标记。如果另一方同时在它收到SYN标记的端口通话,它将发回一个SYN+ACK:SYN和ACK标志位都被打开,并将ACK(确认)编 号字段设定为刚收到的那个数据包的顺序号字段的值。接下来,连接发起方为了表示收到了这个SYN+ACK信息,会向发送方发送一个最终的确认信息(ACK 包)。这种SYN、SYN+ACK、ACK的步骤被称为TCP连接建立时的“三次握手”。在这之后,连接就建立起来了。这个连接将一直保持活动状态,直到 超时或者任何一方发出一个FIN(结束)信号。
任何一方都可以关闭一个TCP连接,要求双方发送一个FIN信号关闭自己的通讯频道。一方可以在另 一方之前关闭,或者双方同时关闭TCP连接。因此,当一方发送一个FIN信号时,另一方可发送“FIN+ACK”,开始关闭自己一方的通信并且确认收到了 第一个FIN信号。发送第一个FIN信号的人接下来再发送一个“FIN+ACK”信息,确认收到第二个FIN信号。另一方就知道这个连接已经关闭了,并且 关闭了自己的连接。发送第一个FIN的人没有办法收到最后一个ACK信号的确认信息。这时它会进入“TIME_WAIT”(等待时间)状态并启动一个定时 器,防止另一方没有收到ACK信息并且认为连接仍是打开的。一般来说,这个状态会持续1至2分钟。
现在,我们来讨论第一个问题。如果有人(假如一 个黑客)在你的Web服务器上留下一个半开或者半关的连接,那就是一个坏消息。每一个连接都要消耗内存,打开数千个虚假的TCP连接可能导致服务器瘫痪。 当然,你实际上不可能在不影响TCP正常工作的情况下调整TCP定时器。如果你听说过TCP SYN 攻击的话,那就是这个意思。为了防止出现这种情况,大多数操作系统都要限制半开连接的数量。例如,Linux默认的限制一般是256个。
关于持续 流控制问题,现在我们就来讨论这个问题。TCP中实现它的机制是TCP滑动窗口机制。TCP协议使用“重新发送与正向ACK”来保证数据传输的可靠性。发 送方将等待一段时间,如果没有收到其发送的数据包的ACK确认信息,发送方就要重新发送。顺便说一下,TCP协议中有许多定时器。这只是其中一个定时器。 ACK的概念对于流控制是非常重要的,因为TCP滑动窗口协议使TCP的往复确认变得更有效率。如果TCP要发送一个数据包并且等待每一个ACK确认信 息,它实际上就把数据吞吐量削减了一半。
理想的情况是,我们能够一次发送许多数据包,然后等待收到一个确认收到全部数据包的ACK信息,而不用对 方发来更多的数据。但是,我们如何知道发送了多少个数据包呢?TCP窗口尺寸可以控制在“已发送但是没有确认”的状态下能够容纳多少个数据包。如果这个窗 口尺寸很大,我们不必等待ACK信息就可以发送大量的数据包。这实际上就是流控制。
接收方就是控制窗口大小的那一方。如果接收方将窗口大小设为 “0”,那么,发送方根本就不能发送任何数据。如果这个窗口的尺寸是“1”,那么,我们就回到了简单的“发送和等待ACK”的协议。如果最后的窗口尺寸是 “0”,发送者将发出一个探测信号以搞清这个窗口什么时间再次打开。如果发送方从来没有收到ACK信息,它就一直不断地重试,直到定时器过期。请记住,这 个窗口尺寸在TCP头中是一个16位字段。如果你要一个窗口尺寸(按字节计算)大于16位可以表示的容量(2的16次方个字节),还可以使用一个名为“窗 口缩放”的TCP协议选项。这个选项允许窗口尺寸乘以比例因子。如果没有极大的窗口尺寸,TCP协议就就无法充分利用GB级别的高速连接。这也是我们需要 针对这些新的高速连接调整TCP参数的原因,
关于TCP流控制的问题,我们不能不提一下Nagle算法。如果我们在一个telnet连接上使用一 个大的TCP窗口会发生什么事情呢?你会输入一个指令(例如敲了一个字母),然后一直等待回应它却迟迟不出现在终端回显上。这对于实时通信来说是一个大问 题。而且,telnet也会增加网络的阻塞度,因为一个字节的数据(例如我们的一次击键)需要40个字节的包头。于是RFC 896定义这个Nagle算法,用以消除小的数据包。这个思路是我们应该在数据发送之前给先把小数据集中起来然后一次性发送,以便提高效率。为了更有效 率,它还限定只允许存在一个未经确认的数据段,你在得到确认信息之前不能发送更多的数据。Telnet和互动SSH连接使用TCP_NODELAY套接口 选项启用这个功能,这样当你按下一个按键的时候,你能够立即得到一个回应。
当然,我们仍是忽略了有关TCP协议的许多事情。然而,通过这两篇文章的了解,你应该能够理解其它一些更专业的TCP著作。阻塞控制与流控制不同,本文没有讨论。如果你真的对了解TCP协议的全部工作原理感兴趣,你可以详细阅读TCP RFC。
小结
TCP 协议非常善于解决流控制问题,因此非常适应于许多应用程序。TCP协议中的流控制的含义是:“在收到对发送的数据的确认信息这前,我可以发送多少数据?” 这就是TCP窗口。学习阻塞控制的问题可以留作读者的练习。需要指出的是,在TCP协议之下连接速度开始很慢,然后速度逐渐加快。这个做法并不总是最理想的。

点这里看TCP/IP协议:网络协议最全篇

posted on 2019-10-17 22:14  jueyuanfengsheng  阅读(605)  评论(0编辑  收藏  举报