zoukankan      html  css  js  c++  java
  • 网络基础知识

    网络基础知识

    osi 七层协议

    image-20200813153850827
    # 此处特别说明,在数据链路层传输时,分为在局域网类和在非局域网类,(通过ip和子网掩码进行and预算 可以得出是否两个ip处于同一个局域网类)都是用mac地址找寻,在局域网类,用广播,在非局域网类,要先通过网关的ip和mac地址传输出去,通过arp协议,将目标的mac地址拿到,然后正式发送数据的时候携带目标ip和网关的mac出网关(网关有两个地址,一个是对局域网内的,一个对外的)
    # osi七层协议时arp协议时属于数据数据链路层,tcp/ip五层协议时属于网路层
    

    tcpudp协议

    image-20200813155221222
    # 此处特别说明 tcp协议比udp协议安全的关键点,因为tcp中会等数据发送完毕,确认对方收到才会删除本地的文件,而udp无论对方是否收到,都会将本地文件发送后删除,tcp协议再没有收到对方的确认后,会再次隔一段时间再次发送数据
    # 途中标识了返回确认信息处应该没有时间间隔
    # udp协议特点,无连接,速度快,可能丢消息,传递数据有长度限制 ,跟传递设备有关,
    应用场景 tcp 文件的上传和下载 如缓存视频是属于tcp,而在线看视频是属于udp
    udp 主要应用于及时通讯类的
    # io操作,(input output)操作,输入和输入是相对内存来说的,write send----output  read  recv----input
    

    socket

    # socket.AF_INET IPv4(默认)
    # socket.AF_INET6 IPv6
    # socket.AF_UNIX 只能够用于单一的Unix系统进程间通信
    
    参数二:类型
    # socket.SOCK_STREAM  流式socket , for TCP (默认)
    # socket.SOCK_DGRAM   数据报式socket , for UDP
    socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
    socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
    socket.SOCK_SEQPACKET 可靠的连续数据包服务
    参数三:协议
    # 0(默认)与特定的地址家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议
    
    """
    服务端应该满足的特性:
        1、一直对外提供服务
        2、并发地提供服务
    """
    import socket
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # AF_INET基于网络类型   SOCK_STREAM=》TCP协议
    # 2、插手机卡
    phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #它在bind前加 ,断开时操作系统还没回收端口号的时候加这句
    phone.bind(("127.0.0.1", 8080))  # 本地回环
    # 3、开机
    print('111111')
    phone.listen(5)
    print('starting %s:%s' %("127.0.0.1", 8080))
    # 4、等电话链接=>链接循环
    while True:
        conn, client_addr = phone.accept()
        print(client_addr)
        # 5、收/发消息=>通信循环
        while True:
            try:
                data = conn.recv(1024)  # 最大接收的字节个数
                if len(data) == 0:  # 针对linux系统,因客户端意外断开连接的时候linux的接受的数据全部都是0
                    break
                print("收到的客户端数据:", data.decode('utf-8'))
                conn.send(data.upper())
            except Exception:  # 针对windows系统,因客户端意外断开连接的时候window会报错
                break
        # 6、关闭
        conn.close()  # 挂电话
    phone.close()  # 关机
    
    # # 客户端
    import socket
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # SOCK_STREAM=》TCP协议
    # 2、拨电话
    phone.connect(("127.0.0.1", 8080))
    # 3、发/收消息=>通信循环
    while True:
        msg = input(">>: ").strip()
        phone.send(msg.encode('utf-8'))
        data = phone.recv(1024)
        print("服务的返回的数据:", data.decode('utf-8'))
    # 4、关闭
    phone.close()
    

    粘包问题

    # 粘包问题只会出现在tcp协议中,而不会出现在udp协议中,其中粘包问题主要是因为接受方不知到消息的界限,不知道一次性提取多少字节造成的,主要原因是由于tcp协议本省造成的,tcp为了提高效率,发送方往往要收集到足够多的数据后才会发送一个tcp,如果每次发送的数据很少,而且时间间隔很短,tcp会根据自身的优化算法将其合成一个tcp片段发送,这样接收方就收到了粘包数据
    # 两种情况下的粘包问题 1. 发送端需要等到缓冲区满才能发送出去,数据时间间隔短,数据时间小,会和到一起,产生粘包;2. 接收方不及时接收缓冲区的包,造成多个包接收,可u后端发送了一段数据,服务端只收了一小部分,服务端下次在接受的时候还是从缓冲区拿上次遗留的数据,产生粘包
    # 解决粘包问题,为字节流加上固定长度的报头,包头宝航字节流长度,然后一次发送到对方,对方在接受时,先从缓存中读取定长的报头,然后再取真实数据,此中,需要用到struct模块
    对于服务端和客户端来说,在接收消息的时候都会经过从缓存区拿去数据问题,需要注意的是无论接受数据的多少,tcp都会将消息的数据排列完整后才会呈现在内核缓存区,
    
    image-20200816114610369
    # 远程连接  服务端
    import socket
    import subprocess
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # SOCK_STREAM=》TCP协议
    # 2、插手机卡
    phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 就是它,在bind前加
    phone.bind(("127.0.0.1", 8080))  # 本地回环
    # 3、开机
    phone.listen(5)
    print('starting %s:%s' % ("127.0.0.1", 8080))
    # 4、等电话链接=>链接循环
    while True:
        conn, client_addr = phone.accept()
        print(client_addr)
        # 5、收/发消息=>通信循环
        while True:
            try:
                cmd = conn.recv(1024)  # 最大接收的字节个数
                if len(cmd) == 0:  # 针对linux系统
                    break
                obj = subprocess.Popen(cmd.decode('utf-8'),
                                       shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
                res=obj.stdout.read()+obj.stderr.read()  # ???
                print(res)
                conn.send(res)
            except Exception:  # 针对windows系统
                break
        # 6、关闭
        conn.close()  # 挂电话
    phone.close()  # 关机
    
    # 客户端
    import socket
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # SOCK_STREAM=》TCP协议
    # 2、拨电话
    phone.connect(("127.0.0.1", 8080))
    # 3、发/收消息=>通信循环
    while True:
        cmd = input("[root@localhost]# ").strip()
        phone.send(cmd.encode('utf-8'))
        data = phone.recv(1024)
        print(data.decode('gbk'))
    # 4、关闭
    phone.close()
    
  • 相关阅读:
    unbuntu下安装多个JAVA JDK版本及如何切换
    google play上获取apk文件
    android开发里跳过的坑——android studio打包的APK签名无效
    android studio配置so文件路径
    Android 4.4.2上与BLE 蓝牙锁设备的通讯
    android 上AES解密是报错javax.crypto.BadPaddingException: pad block corrupted
    android开发里跳过的坑——listview不显示
    如何在Linux服务器中使用arping命令
    如何在CentOS 8上安装OpenLiteSpeed
    如何在Ubuntu 20.04 LTS系统上安装ModSecurity Apache
  • 原文地址:https://www.cnblogs.com/feiguoguobokeyuan/p/13560556.html
Copyright © 2011-2022 走看看