zoukankan      html  css  js  c++  java
  • UDP协议, DNS

    1.UDP协议

    UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection 参考模型中一种无连接的传输层协议,提供简单不可靠信息传送服务

    是一种无连接的传输层协议,它主要用于不要求分组顺序到达的传输中,分组传输顺序的检查与排序由应用层完成。且不对传送数据包进行可靠性保证,适合于一次传输少量数据。

     

    2.UDP 通讯流程

    UDP通讯流程与对讲机非常类似

    买传呼机 == socket() 固定对讲频道 == bind() 收信号 == recvfrom() 发信号 == sendto() 由于不需要建立 连接所以省去 TCP的listen()和accept()这两步

    3.UDP的使用

    # 客户端
    import  socket
    
    c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    
    while True:
        data = input(">>:")
        c.sendto(data.encode("utf-8"),("127.0.0.1",9999))
        msg = c.recvfrom(1024)
        print(msg)
        
    # 服务器
    import  socket
    c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    c.bind(("127.0.0.1",9999))
    while True:
        msg,addr = c.recvfrom(1024)
           c.sendto(msg.upper(),addr)

    4.UDP与TCP的具体传输过程分析对比:

      TCP在传输过程中需要保证数据的完整性,所以当数据从操作系统缓存发出时,并不会立即删除缓存数据,而是等待对方返回确认信息后才会删除,

      而UDP发送后立即清空数据,所以数据发送是一次性的,无论成功还是失败,所以会造成数据丢失,当然TCP也会丢失但是会有自动重传机制。

     

    不会粘包

    另外UDP是基于数据报的,每一次发送都是一个单独的数据报,所以不会产生粘包问题

    测试:

    # 服务器 仅接受一次 并且接受长度 大于对方的发送数据长度
    import  socket
    
    c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    c.bind(("127.0.0.1",9991))
    msg,addr = c.recvfrom(1024)
    print(msg.decode("utf-8"))
    
    
    # 客户端 发送两次数据
    import  socket
    
    c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    c.sendto("hello".encode("utf-8"),("127.0.0.1",9991))
    c.sendto("world".encode("utf-8"),("127.0.0.1",9991))

    注意1:发送方的数据长度应与接收方的接受长度统一,否则将丢失数据,windows下直接报错。

    # 修改上例中的服务器
    import  socket
    c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    c.bind(("127.0.0.1",9991))
    msg,addr = c.recvfrom(1)
    print(msg.decode("utf-8"))
    #输出:
    # h 
    # w

     

    注意2:缓存区大小不可能无限大,如果要传输大数据超过UDP数据报大小,则需要在UDP基础上加上额外的应用层协议。

    并且即使缓冲区足够仍会出现数据丢失,UDP的最大数据长度为 1472

    以下是计算方式:

    1.在链路层,由以太网的物理特性决定了数据帧的长度为64+18-1500+18,其中的18是数据帧的头和尾,也就是说数据帧的内容最大为1500(不包括帧头和帧尾),即MTU(Maximum Transmission Unit)为1500;   2.在网络层,因为IP包的首部要占用20字节,所以这的MTU为1500-20=1480;  3.在传输层,对于UDP包的首部要占用8字节,所以这的MTU为1480-8=1472;   

    所以,在应用层,你的Data最大长度为1472。当我们的UDP包中的数据多于MTU(1472)时,发送方的IP层需要分片fragmentation进行传输,而在接收方IP层则需要进行数据报重组,由于UDP是不可靠的传输协议,如果分片丢失导致重组失败,将导致UDP数据包被丢弃。

     

     

    5.基于UDP的时间服务器练习

    向服务器发送带有时间格式的数据报

    # 服务器
    import socket
    import time
    
    c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    c.bind(("127.0.0.1",8888))
    
    while True:
        fmt,addr = c.recvfrom(1024)
        c.sendto(time.strftime(fmt.decode("utf-8"),time.localtime()).encode("utf-8"),addr)
    
        
    # 客户端
    import socket
    c = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    c.sendto("%Y-%m-%d %H:%M:%S %p".encode("utf-8"),("127.0.0.1",8888))
    print(c.recvfrom(1024)[0])

    7.UDP的应用:之DNS

    网络请求的具体流程

    我们的socket的程序要想完成通讯都需要知道服务器的IP的端口,而我们在使用浏览器访问网页时并没有指定服务器的IP和端口,这是为什么呢?

     

    我们都知道,两台计算机要通讯则必须知道对方的IP地址,但是IP地址较复杂不方便记忆,造成用户上网成本高,体验差,于是就想到了给IP地址取别名的办法,这就是域名。如www.baidu.com

    域名:

    是给IP地址取的别名,同时为了在查询名字与地址对应关系时更快,所以给域名也划分了不同区域。

    分类

    1.1 国际顶级域名,工商企业.com .top,网络提供商.net,非营利性组织.org,教育.edu

    1.2 国际域名,中国.cn,美国.us,日本.jp

    但随之而来的问题是域名虽然简化了记忆,但是数据传输依然要依赖IP地址和端口,所以想要还要提供一个可以通过域名获取ip的机制,这就是DNS

    DNS

    全称域名解析服务器,其本质上就是一个大型数据库系统

    DNS访问流程:

    当我们要访问一个地址如www.baidu.com

    1.浏览器首先会询问本地DNS服务器(即网络运营商如电信,联通),以获取对应的IP,

    2.如果本地DNS中没有想要的记录,则本地DNS,会询问根(1级)域名服务器,全球有13台

    根域名服务器中不可能存储全世界所有IP所以它仅存储顶级(2级)域名服务器的IP

    例如:COM域主服务器的IP,NET域主服务器的IP

    3.于是本地DNS得到COM域服务器IP后向其发送请求,

    4.由于一个域名可以对应多个IP所以还需要向三级域名主机发出请求

    5.最后将返回的IP信息缓存到本地DNS中备用

     

    DNS的问题

    这样一来就造成一个问题 当一个已存在的域名更换IP后在一段时间内是无法访问的,因为子域名服务器需要到达指定时间后才会自动刷新纪录

     

    8.目前的问题

    TCP中只能处理一个客户端的数据

    UDP虽然看起来可以同时处理,但本质上也是按照顺序来处理的

    为了提高用户访问速度,必需找到一种可以使得服务器可以同时处理多个客户端请求的能力

    这就需要使用并发编程了

  • 相关阅读:
    Data truncation: Out of range value for column 'quanity' at row 问题解决方案
    nginx 提示the "ssl" directive is deprecated, use the "listen ... ssl" directive instead
    集合源码分析[3]-ArrayList 源码分析
    集合源码分析[2]-AbstractList 源码分析
    IDEA升级版本后界面出现变小,字体变细的问题解决
    集合源码分析[1]-Collection 源码分析
    kubernetes学习第一篇-k8s安装以及HelloWorld
    shiro多Realm第一次调用不生效问题
    设计模式学习(二)-简单工厂模式
    根据具体的地址解析出对应的地区码
  • 原文地址:https://www.cnblogs.com/HZLS/p/10959397.html
Copyright © 2011-2022 走看看