OSI七层网络模型
应用层Application
模型的最高层,为用户的应用程序提供网络服务。负责完成网络中应用程序域网络操作系统之间的联系,建立与结束使用这之间的联系,并完成网络用户提出的各种网络服务及应用所需的监督、管理和服务等各种协议。负责协调各个应用程序间的工作。
应用层为用户提供的服务和协议有:文件服务、目录服务、文件传输服务(FTP),远程登陆服务(TeInet)、电子邮件服务(E-mail)、打印服务、安全服务、网络管理服务、数据库服务等。表示层Presentation
对应用层的命令和数据进行解释,对各种语法赋予相应的含义,按照一定的格式传送给会话层。
主要功能是处理用户信息的表示问题(编码、数据格式和加密解密、压缩、解压缩等)。
会话层Session
负责在网络中的两节点之间建立、维持、和终止通信。建立通信连接、保持会话过程通信链接的畅通、同步两个节点之间的对话,决定通信是否被中断已经通信中断时决定从何处重新发送。(不同机器上的用户之间会话的建立及管理)。传输层Transport
像上明的应用层提供通信服务,面向通信部分的最高层,也是用户功能中的最底层。接收会话层数据,在必要时将数据进行分割,并将这些数据交给网络层,并且保证这些数据段有效的到达对端。此次的单位是:数据段。TCP传输控制协议和UD P用户数据报协议。网络层Network
主要功能是将网络地址翻译成对应的物理地址,并决定如何将数据从发送方路由到接收方。建立网络连接和为上层提供服务。
数据链路层DataLink
数据通道,主要功能睡如何在不依靠的物理线路上进行数据的可靠传递。作用包括:物理地址寻址,数据的成帧,流量控制、数据检错及重发。物理层Physical
设备之间的数据通信提供传输媒体及互联设备,为数据传输提供可靠的环境。
OSI七层模型是一个理想模型。每一层都提供一个特殊的网络功能,从网络角度观察:
下4层(物理层、数据链路层、网络层和传输层):主要提供数据传输和交换功能,即以节点到节点之间的通信为主。
第四层作为上下两部分的桥梁,是整个网络体系结构中最关键的部分。
上3层(会话层、表示层、应用层):以提供用户与应用程序之间的信息和数据处理功能为主。

TCP和UDP
-
IP地址
为了实现网络中不同终端之间的通信,每个终端都必须有一个唯一的标识--IP地址 -
端口
1、用于区分不同的应用程序
2、端口号的范围0-65535,其中0-1923为系统的保留端口,我们的程序尽可能的不使用这些端口。
3、IP地址和端口号组成socket,socket是网络运行程序间双向通信链路的终结点。是TCP和UDP的基础。
4、常用协议使用的端口:HHTP:80,FTP:21,TELENT:23 - TCP协议流程
TCP(Transmission Control Protocol,传输控制协议)是面向连接的协议,在收发数据前都需要和对面建立可靠的链接。
三次握手
建立一个TCP连接时需要客户端和服务端总共发送3个包确认连接建立
- 1、
Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给server,Client今入SYN_SENT状态,等待server确认。 - 2、
Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client确认连接请求,Server进入SYN_RCVD状态。 - 3、
Client收到确认后,检查ack是否为J+1,ACK是否为1,正确则将标志位ACK置为1,ack=K+1,并将该数据包发送Server,Server检查ack是否为K+1,ACK是否为1,正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成3次握手。随后Client和Server之间可以开始传输数据了。
四次挥手
终止TCP连接,需要客户端和服务端总共发送4个包以确认连接的断开。
- 1、
Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入到FIN_WAIT_1状态。 - 2、
Server收到FIN后发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。 - 3、
Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。 - 4、
Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号收到序号+1,Server进入CLOSED状态,完成四次挥手。
四次挥手.png
另外同时发起主动关闭的情况。

Server在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给Client,而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不在发送数据了但是还能接受数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一下数据给对方后,在发送FIN报文给对方来表示同意现在关闭连接,因此己方ACK和FIN一般都会分开发送。
UDP
UDP(User Datagram Potocol)用户数据报协议,非连接的协议,在传输数据之前源端和终端不建立连接,传送时就简单的去抓取来自应用程序的数据,并尽可能快的把它扔到网络上。
发送端:UDP传送数据的速度仅仅是受到应用程序生成数据的速度、计算机的能力、传输带宽的限制。
接收端:UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
相比TCP就是无需建立连接,结构简单,无法保证正确性,容易丢包。
| TCP | UDP |
|---|---|
| 基于连接 | 无连接 |
| 流模式 | 数据报模式 |
| 保证数据正确性 | 可以丢包 |
| 保证数据顺序 | 不保证 |
| 对系统资源的要求较多 | 对系统资源的要求较少 |
| 程序结构较简单 |
Socket
Socket就像插座,负责连通两端的设备,进行点对点的通信。端口像插座上的孔,谁接通这个IP+端口就和谁进行通信(端口绑定在应用进程上)。socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为简单的接口供应用层调用实现进程在网络中的通信。起源于UNIX,在其一切姐文件的思想,进程间通信就被冠名为文件描述符(file descriptor),socket是一种打开--读/写--关闭模式的实现。server和client各自维护一个文件。建立连接后,可以向文件写入内容供对方读取或着读取对方内容,通信结束关闭文件。

主要类型
1、流套接字SOCK_STREAM
流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复送,并按顺序接受。可以SOCK_STREAM当成一条传送带,只有传送带本身没有问题(不断网),数据就不会丢失,并且晚传送的数据不会早到,早传送的数据不会晚到。
数据发送和接收不同步:
流格式套接字的内部有一个缓冲区(字符数组),通过socket传输的数据将保存在这个缓冲区。接收端在收到数据后并不一定立即读取,只要数据不超过缓冲区的容量,接收端有可能在缓冲区被填满后一次性读取,也可能分成好几次读取。流式套接字使用TCP`协议(The Transmission Control Protocol,传输控制协议)。
特点:
- 数据在传输过程中不会消失
- 数据按照顺序传输
- 数据的发送和接收不是同步的
2、数据报套接字SOCK_DGRAM
数据报套接字提供一种无连接、不可靠的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序的接收数据。
使用的UDP(User Datagram Protocol)协议进行数据传输。对于有可能出现的数据丢失情况,需要在程序中做相应的处理。
计算机只管传输数据,不作数据校验,如果数据在传输中损坏,或者没有到达另一台计算机,是没有办法补救的。
数据报套接字所做的校验工作少,在传输效率方面比流格式套接字要高。
视频聊天和语语音聊天使用SOCK_DGRAM来传输数据,因为首先要保证通信的效率,尽量减小延迟,而数据的正确性是次要的,即使丢失很小的一部分数据,视频和音频也能正常解析,最多出现噪点和杂音,不会对通信质量有实质的影响。
注意SOCK_DGRAM没有想象中的糟糕,不会频繁的丢失数据,数据错误只是小概率事件。
特点
- 强调快速传输而非传输顺序
- 传输的数据可能丢失也能损毁
- 限制每次传输的数据大小
- 数据的发送和接收是同步的
3、原始套接字SOCK_RAW
原始套接字可以读写内核没有处理的IP数据报,流式套接字只能读取TCP协议,数据报套接字只能读取UDP`协议的数据。如果要访问其他协议发送的数据必须使用原始套接。主要用于一些协议的开发,可以进行比较底层的操作。
Socket通信流程
socket通信两端都建立了一个socket对象,然后通过socket对象对数据进行传输。通常服务器处于一个无限循环状态,等待客户端的连接。

-
服务端过程1、服务端先初始化
socket,建立流式套接字,2、
bind((host, port)) 绑定IP及端口,listen()通知TCP准备好接收连接,3、
建立连接时accept()返回新socket对象,继续阻塞等待其他客户端的连接。 (con,addr)=socket.appect(),con是新的socket对象,addr是客户端的IP和端口。-
4、服务器和客户端通过
send()和revc()通信(传输数据)。服务器调用
recv()从客户端接收信息。调用recv()时,服务器必须指定定一个整数,它对应于可通过本次方法调用来接收的最大数据量。recv() 在接收数据时会进入blocked状态,最后返回一个字符串,用它表示收到的数据。如果发送的数据量超过了 recv() 所允许的,数据会被截短。多余的数据将缓冲于接收端,以后调用recv()时,会继续读剩余的字节,如果有多余的数据会从缓冲区删除(以及自上次调用recv()以来,客户端可能发送的其它任何数据)。
服务器调用send(),向客户端发送信息,send()返回已发送的字符个数。 5、传输结束,服务器调用
Socket的close()关闭连接。
客户端过程
客户端的过程比较简单,创建socket,连接服务器,发送数据,读取响应数据,直到数据交互完毕,关闭连接,结束TCP对话。
Socket的TCP三次握手

- 1、服务器调用
socket()、bind()、listen()完成后,调用accept()阻塞等待客户端连接。 - 2、
客户端socket()对象调用connect()向服务器发送一个SYN并阻塞等待。 - 3、
服务器完成了第一次握手,即发送SYN和ACK应答。 - 4、
客户端收到服务端发送的应答之后,从connect()返回,在发送一个ACK给服务器。 - 5、
服务器socket对象接收客户端第三次握手ACK确认,服务器从accept()返回,建立连接。
Socket的TCP四次挥手

- 1、某个应用程序调用
close()主动关闭,发送一个FIN。 - 2、另一端收到
FIN后被动执行关闭,并发送ACK进行确认。 - 3、
被动执行关闭的应用程序调用close()关闭socket,并发送一个FIN。 - 4、
接收到这个FIN的一端向另一端发送ACK确认。
简单示例
- server端
import socket
# 创建 socket 对象
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# ip地址 端口号
host = '127.0.0.1'
port = 9999
# 绑定端口号
serversocket.bind((host, port))
# 设置最大连接数,超过后排队
serversocket.listen(5)
while True:
# 建立客户端连接
clientsocket, addr = serversocket.accept()
print("连接地址: %s" % str(addr))
msg = 'hello 欢迎'
clientsocket.send(msg.encode('utf-8'))
data = clientsocket.recv(1024)
print('client msg:' + data.decode('utf-8'))
clientsocket.close()
- client端
# 导入 socket、sys 模块
import socket
# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# ip地址
host = '127.0.0.1'
# 设置端口号
port = 9999
# 连接服务,指定主机和端口
s.connect((host, port))
# 接收小于 1024 字节的数据
msg = s.recv(1024)
print (msg.decode('utf-8'))
con=input('请输入内容:')
s.send(con.encode('utf-8'))
s.close()
//连接成功后收到服务端发送的信息
hello 欢迎,
//向服务端发送信息
请输入内容:你好
//服务端接受到信息
client msg:你好
