今天的内容进入网络编程的概念
OSI七层模型:应用层,表示层,会话层,传输层,网络层,链路层,物理层
OSI七层模型是国际标准化组织制定的网络互联模型,他的优点是:
1.建立了统一的网络工作流程
2.每个层次功能清晰,各司其职
3.降低了耦合度,方便了开发流程
但是我们在实际的运用中,用的更多是的四层模型的概念,这里的四层模型就是将上述的七层模型简化为四层,合并其中的几层而已,四层模型分别是:应用层,传输层,网络层,物理层,这也就是我们所说的TCP/IP模型。
以上是网络的基础理论,下面我们来说说基于TCP/IP协议的传输层连接过程和断开过程。总结为三次握手和四次挥手。
三次握手建立连接:
1.客户端像服务端发送连接请求
2.服务端收到客户端请求报文(消息序列号),回复报文消息,表示可以连接
3.客户端收到服务端回复,再次发送报文最终建立连接
四次挥手断开连接:
1.主动方发送报文提出断开连接
2.被动方接受的断开请求,立即返回消息表示开始准备断开
3.被动方处理消息完毕,完成断开准备,再次发送报文表示可以断开
4.主动方收到断开指令,发送报文最终确认断开
这就是TCP协议下的连接和断开过程,这个很重要,一定要知道。
那么用TCP协议来连接和传输数据有什么特点呢?一个词语就可以总结:可靠。
这里的可靠是指在传输数据的过程中:无丢失,无失序,无差错,无重复,所以我们通常使用的邮件系统和需要保证数据的准确性的系统在传输层都是基于TCP协议来实现的。
面向无连接的协议:UDP协议
基于TCP协议的传输需要先连接之后才能传输数据,但是UDP协议就正好相反,基于UDP协议的传输服务就不需要连接,可以直接传输数据,但是它的特点也是很明显的,不可靠,在传输数据的过程中,数据有可能会丢失,混乱。
存在即有用,UDP协议也有他适合的应用场景,比如对数据可靠性要求不高的地方,如:视频,群聊,广播等。即使在网络状况较差的情况下,也能使用,但是TCP就不适合在网络情况较差的情况下使用。
应用层的协议:HTTP协议
相信很多人都对这个协议有所耳闻,因为他太有名了,会上网的都知道,但是也仅仅只是知道,它的作用简直不要太重要。
http协议:超文本传输协议,是应用在应用层的协议。它的作用是用于网页的获取和数据的传输。所以,如果没有这个协议,那么你经常用的百度的那个搜索界面都是打不开的。
特点:
1.应用层协议,传输层采用tcp方式收发消息
2.简单,灵活,很多语言都有http协议接口
3.无状态的协议,协议本身不要求记录传输数据
4.http1.1开始支持持久连接
网页的请求过程:
1.客户端(浏览器)通过tcp传输,发送http请求给服务器
2.服务器收到http请求后进行解析
3.服务器处理具体请求内容,整理需要的数据
4.将数据以http响应的格式回发给浏览器(客户端)
5.浏览器接收相应,显示内容
对于请求,一共有好几种请求方式,我们只知道两种请求方式就可以了,最常用的也只有这两种,如果有兴趣,可以去看看其他的请求方式。这两种方式是:get请求和post请求
对于响应,就只有一种:response。
socket模块
这个模块是python的标准库模块,提供网络编程的一系列接口。
无论是实现以TCP的方式的传输还是以UDP方式的传输,都可以用这个模块实现。只不过TCP要多写几行代码,毕竟我们是需要连接的,而UDP可以少写几行。
首先展示下TCP方式的传输示例:
服务器端代码:
import socket
sockfd=socket.socket(socket_family=socket.AF_INET,socket_type=socket.SOCK_STREAM,proto=0)
#上面的这个socket()方法是不是觉得有好多好多参数?其实这些参数我们都可以用默认值,如果我们都不写,
用默认值,那么默认使用TCP传输,如果需要用UDP传输,那么就得设置socket_type参数的值为:socket.SOCK_DGRAM
#这样我们就设置好了服务器端采用那种传输方式传输了,接下来是绑定地址
sockfd.bind((0'127.0.0.1',12000)) 这里的参数一定要是一个元组
#设置监听
sockfd.listen(n) 参数n为需要监听队列的大小,也就是监听的数量
#等待处理客户端消息
connfd,addr = sockfd.accept()
#connfd是生成的新的套接字,专属于某一个连接进来的客户端,而addr是连接进来的这个客户端的地址,也是元组
data = cnnfd.recv(bufffersize) #这是等带连接的客户端发送消息,客户端发送给服务器的消息用变量data绑定
n = connfd.send(data) #这是发送消息给连接进来的那个客户端,想发什么数据发什么数据,但是注意,消息一定是二进制的格式,返回值n是发送消息的字节数
connfd.close()
sockfd.close()
#消息接收和发送都完成了,那么我们就要关闭套接字
客户端代码示例:
import socket
#创建TCP套接字
sockfd = socket.socket()
#发起连接
sockfd.connect(('176.221.13.169',25000))
#消息收发
data = input('请输入')
sockfd.send(data.encode()) #发送消息
data = sockfd.recv(1024) #一次最多接收1024个字节
sockfd.close()
sockfd.close()
好了,基于TCP传输的客户端和服务器端的代码示例就是这样的,这其实就是传输数据底层的实现方式。其实也不算太底层,原生,原生方法传输数据就是这样的。
下面是UDP方式传输示例,可以参照TCP来看,几乎都差不多,只是代码更少。
服务器端:
sockfd = socket(socket.AF_INET,socket.SOCK_DGRAM) #创建套接字
sockfd.bind((0'127.0.0.1',12000)) #绑定地址
data,addr = sockfd.recvfrom(buffersize) #消息接收
n = sockfd.sendto(data,addr) #消息发送
sockfd.close() #关闭套接字
客户端:
sockfd = socket(socket.AF_INET,socket.SOCK_DGRAM) #创建套接字
n = sockfd.sendto(data,addr) #发送消息,addr就是服务端绑定的那个地址,data就是需要发给服务端的数据,n为发送字节数
data,addr = sockfd.recvfrom(buffersize) #消息接收,每次就收的数量为buffersize。自定义的
sockfd.close() #关闭套接字
UDP比TCP实现起来更简单
TCP套接字和UDP套接字的区别
1.tcp套接字以字节流的方式传递,数据报套接字以数据报形式传递
2.tcp传输会有粘包,udp不会(有边界消息)
3.tcp传输保证传输可靠性,udp则会有部分消息丢失的可能
4.tcp需要listen accpet 保证连接,udp不需要
5.tcp使用send,recv收发消息,udp使用sendto,recvfrom收发消息