七层协议

一、网络编程

#C/S架构
  提供数据的一方称之为服务器(Server),访问数据的一方称之为客户端(Client)(基于浏览器B/S)

#网络通讯的基本要素
  两台计算机要通讯,必须要具备两个基本要素

    1、物理连接介质(包括网线,无线电,光纤等)
    2、通讯协议

 

二、网络通讯协议

  OSI  开放式系统互联通信参考模型

7层 数据格式  功能与连接方式  典型设备
应用层Application    网络服务于使用者应用程序间的一个接口  
表示层Presentation    数据表示、数据安全、数据压缩  
会话层Session    建立、管理和终止会话  
传输层Ttransport  数据组织成数据段Segment  用一个寻址机制来标识一个特定的应用程序(端口号)  四层交换机、四层路由器
网络层Network  分割和重新组合数据报Packet  基于网路层地址(IP地址)进行不同网络系统间的路径选择  路由器、三层交换机
数据链路层Data Link  将比特信息封装成数据帧Frame  通过使用接收系统放硬件地址或物理地址寻址  网桥、交换机、网卡
物理层Physicai  传输比特(bit)流  建立、维护和取消物理连接  光纤、同轴电缆、双绞线、中继器和集线器 


 

 三、各层功能

 1、物理层

#第一层、物理层  规定物理介质的相关规范(电缆,光纤)
    物流层的功能:基于电子器件发送电流信号,根据电流高低对应0、1,也就是二进制位
    它的问题是:对方不知道二进制到底什么含义,每一次到底读多少位二进制
View Code

2、数据链路层

#规定了电信号的分组方式
    以太网协议,MAC地址,广播


#1、以太网协议:

早期的时候各个公司都有自己的分组方式,后来形成了统一的标准,即以太网协议ethernet

ethernet规定

    一组电信号构成一个数据包,叫做‘帧’
    每一数据帧分成:报头head和数据data两部分
       head                           data                             
 

head包含:(固定18个字节)
    发送者/源地址,6个字节
    接收者/目标地址,6个字节
    数据类型,6个字节

data包含:(最短46字节,最长1500字节)
    数据包的具体内容

head长度+data长度=最短64字节,最长1518字节,超过最大限制就分片发送

#mac地址:
head中包含的源和目标地址由来:ethernet规定接入internet的设备都必须具备网卡,发送端和接收端的地址便是指网卡的地址,即mac地址

mac地址:每块网卡出厂时都被烧制上一个世界唯一的mac地址,长度为48位2进制,通常由12位16进制数表示(前六位是厂商编号,后六位是流水线号)


#广播:
有了mac地址,同一网络内的两台主机就可以通信了(一台主机通过arp协议获取另外一台主机的mac地址)

ethernet采用最原始的方式,广播的方式进行通信,即计算机通信基本靠吼
View Code

3、网络层

网络层的由来:上层知道通信采用广播的方式,不可能每次都全球广播,所以有了IP协议


#网络层功能:引入一套新的地址用来区分不同的广播域/子网,这套地址即网络地址

#IP协议:
    规定网络地址的协议叫ip协议,它定义的地址称之为ip地址


i#p地址分成两部分

    网络部分:标识子网
    主机部分:标识主机
    注意:单纯的ip地址段只是标识了ip地址的种类,从网络部分或主机部分都无法辨识一个ip所处的子网

#子网掩码
    它在形式上等同于IP地址,也是一个32位二进制数字,它的网络部分全部为1,主机部分全部为0。比如,IP地址172.16.10.1,如果已知网络部分是前24位,主机部分是后8位,那么子网络掩码就是11111111.11111111.11111111.00000000,写成十进制就是255.255.255.0。


#怎么知道是否在同一个子网络
    将两个IP地址与子网掩码分别进行AND运算(两个数位都为1,运算结果为1,否则为0),然后比较结果是否相同,如果是的话,就表明它们在同一个子网络中,否则就不是。


#比如,
    已知IP地址172.16.10.1和172.16.10.2的子网掩码都是255.255.255.0,请问它们是否在同一个子网络?两者与子网掩码分别进行AND运算,

172.16.10.1:10101100.00010000.00001010.000000001

255255.255.255.0:11111111.11111111.11111111.00000000

AND运算得网络地址结果:10101100.00010000.00001010.000000001->172.16.10.0

 

172.16.10.2:10101100.00010000.00001010.000000010

255255.255.255.0:11111111.11111111.11111111.00000000

AND运算得网络地址结果:10101100.00010000.00001010.000000001->172.16.10.0
结果都是172.16.10.0,因此它们在同一个子网络。

#总结一下,IP协议的作用主要有两个,一个是为每一台计算机分配IP地址,另一个是确定哪些地址在同一个子网络。
View Code

4、传输层

传输层由来:
    网络成找到了主机,没有找到应用程序

#传输层功能:
    建立端口到端口的通信

#补充:
    端口范围0-65535,0-1023为系统占用端口

#tcp协议,udp协议,在此层
View Code

5、应用层

#应用层由来:
    用户使用的都是应用程序,均工作于应用层,互联网是开发的,大家都可以开发自己的应用程序,数据多种多样,必须规定好数据的组织形式 

#应用层功能:
    规定应用程序的数据格式。
View Code

 

UDP

  DUP是无链接的,先启动哪一端都不会报错

import socket

s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(("127.0.0.1",5666))
ip_prot = ("127.0.0.1",5666)
while True:
    res,addr = s.recvfrom(1024)
    print(res)
    print(addr)


--------------------------------------------------------------------------
客户端
import socket
c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
ip_port = ("127.0.0.1",5666)
while True:
    msg = input(">>:")
    c.sendto(msg.encode("utf-8"),ip_port)
    c.recvfrom(1024)
简单UDP格式

  对比TCP

   服务器:
    UDP不需要监听和接受请求,
    TCP服务默认只能与一个客户端进行通讯,下个客户端必须等到上个客户端断开链接
    UDP多个客户端请求会被 依次处理,由于不需要建立链接,所以感觉好像是可以同时处理

   客户端:
    不需要建立链接,直接发送即可,可以发送空消息

  当接收方缓冲区的长度小于数据报的长度时,Windows会报异常,而Linux不会,缓冲区多大就接收几个

import socket
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(("127.0.0.1",8899))
res,addr = s.recvfrom(1024)      #即便是1024远大于要发送信息,但仍只打印hello
print(res,addr)

----------------------------------------------------------------------
客户端
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
ip_info = ("127.0.0.1",8899)
client.sendto("hello".encode("utf-8"),ip_info)
client.sendto("world".encode("utf-8"),ip_info)

-----------------------------------------------------------------------

 #如果将缓冲区的1024改为1,Windows会报错
缓冲区小于发送方要发送的内容时

  基于UDP的聊天室练习

import socket
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(("127.0.0.1",8866))
while True:
    res,addr = s.recvfrom(1024)
    print("收到来自%s的消息:%s" %(addr,res.decode("utf-8")))
    msg1 = input(">>:")

    s.sendto(msg1.encode("utf-8"),addr)

---------------------------------------------------------------------------------
客户端一
import socket
c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
    msg = input(">>:")
    if msg =="q":break
    c.sendto(msg.encode("utf-8"),("127.0.0.1",8866))
    res,addr = c.recvfrom(1024)
    print("收到来自%s的消息:%s" %(addr,res.decode("utf-8")))

-------------------------------------------------------------------------------------
客户端二
import socket
c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
    msg = input(">>:")
    if msg =="q":break
    c.sendto(msg.encode("utf-8"),("127.0.0.1",8866))
    res,addr = c.recvfrom(1024)
    print("收到来自%s的消息:%s" %(addr,res.decode("utf-8")))
简单的聊天室

  基于UDP的时间服务器

import socket,time
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(("127.0.0.1",8888))
while True:
    res,addr = s.recvfrom(1024)

    t = time.strftime(res.decode("utf-8"),time.localtime())
    s.sendto(t.encode("utf-8"),addr)
-------------------------------------------------------------------------
import socket
c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
addr = ("127.0.0.1",8888)

fmt = "%Y-%m-%d %H:%M:%S"
c.sendto(fmt.encode("utf-8"),addr)

data,addr = c.recvfrom(1472)
print(data.decode("utf-8"))
时间服务器

  注意:UDP在使用时,必须保证接收方的数据缓冲区的大小,必须大于或等于发送方的数据报大小

  由于缓冲区的大小不可能无限大,所以UDP不适用于数据量较大的情况,如果一定要使用UDP来传输较大数据量的时候,需要自己对数据进行切割,组装。(UDP最大为1472字节)

原文地址:https://www.cnblogs.com/pdun/p/10450464.html