zoukankan      html  css  js  c++  java
  • 五. 网络编程(UDP 不黏包)

    一 .UDP不黏包 会丢包

    1. 不黏包 丢包

    UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务。 
    不会使用块的合并优化算法,, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)
    采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息)
    ,这样,对于接收端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。 对于空消息:tcp是基于数据流的,于是收发的消息不能为空,这就需要在客户端和服务端都添加空消息的处理机制,
    防止程序卡住,而udp是基于数据报的,即便是你输入的是空内容(直接回车),也可以被发送,udp协议会帮你封装上消息头发送过去。 不可靠不黏包的udp协议:udp的recvfrom是阻塞的,一个recvfrom(x)必须对唯一一个sendinto(y)
    ,收完了x个字节的数据就算完成,若是y;x数据就丢失,这意味着udp根本不会粘包,但是会丢数据,不可靠
     用UDP协议发送时,用sendto函数最大能发送数据的长度为:65535- IP头(20) – UDP头(8)=65507字节
    用sendto函数发送数据时,如果发送数据长度大于该值,则函数会返回错误。(丢弃这个包,不进行发送)

    2 .基于udp协议实现不黏包 丢包

     基于UDP先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)

    client1
    
    from socket import *
    ip_port=('127.0.0.1',9000)
    
    client=socket(AF_INET,SOCK_DGRAM)
    while True:
        msg=input('>>: ').strip()
        client.sendto(msg.encode('utf-8'),ip_port)
        err,addr=client.recvfrom(1024)
        out,addr=client.recvfrom(1024)
        if err:
            print('error : %s'%err.decode('utf-8'),end='')
        if out:
            print(out.decode('utf-8'), end='')
    server1
    
    from socket import *
    import subprocess
    
    ip_port=('127.0.0.1',9000)
    
    server=socket(AF_INET,SOCK_DGRAM)
    server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    server.bind(ip_port)
    
    while True:
        #收消息
        cmd,addr=server.recvfrom(1024)
        #逻辑处理
        res=subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=subprocess.PIPE,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
        stderr=res.stderr.read()
        stdout=res.stdout.read()
        #发消息
        server.sendto(stderr,addr)
        server.sendto(stdout,addr)
    server.close()
    server1
    
    # UDP
    # udp 永远 不会黏包
    #只有TCP有粘包现象,UDP永远不会粘包
    # 但是会丢包
    # https://www.cnblogs.com/Eva-J/articles/8244551.html
    # https://www.cnblogs.com/Eva-J/p/7277026.html
    # UDP不会发生黏包
    #_*_coding:utf-8_*_
    from socket import *
    import subprocess
    
    ip_port=('127.0.0.1',9000)
    bufsize=1024
    udp_server=socket(AF_INET,SOCK_DGRAM)
    udp_server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    udp_server.bind(ip_port)
    
    while True:
        #收消息
        cmd,addr=udp_server.recvfrom(bufsize)
        print('用户命令----->',cmd)
    
        #逻辑处理
        res=subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=subprocess.PIPE,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
        stderr=res.stderr.read()
        stdout=res.stdout.read()
    
        #发消息
        udp_server.sendto(stderr,addr)
        udp_server.sendto(stdout,addr)
    udp_server.close()
  • 相关阅读:
    Devexpress [汇总链接]
    [转]修改LayoutControlitem容器内的控件长宽
    How to hide border of XtraTabControl
    CEF / Chromium 重新编译2018 官网地址 一路是坑 千万别跟着官方step by step走一定多思考多查资料 因为改动地方太多了编译都每个版本都不一样
    c#:配置引用程序集的路径(分离exe和dll)和 如何处理[dllImport]中的程序集的加载 [笔记]
    [redis] -- 缓存雪崩和缓存穿透、缓存击穿问题解决方案篇
    [redis] -- 为什么那么快
    [redis] -- 集群篇
    [spring cloud] -- 服务注册与服务发现篇
    [spring cloud] -- 核心篇
  • 原文地址:https://www.cnblogs.com/Sup-to/p/11135505.html
Copyright © 2011-2022 走看看