python网络编程基础--ip地址、osi协议、TCP、UDP、粘包现象、socketserver模块

  1. 网络基础

    打基础
    了解一些网络的基础知识
    简单了解一些底层的网络通信
    3-4天
    网络的概念
    基于原生的网络模块来实现通信
    完成一些简单的程序
    了解一些协议的特点,扬长避短
    概念
    学号:临时的编号/变化的
    身份证号:唯一标识/不变的
    不变的:mac地址 能够唯一标识你这台机器
    变化的:IP地址 能够更方便的找到你的机器
    vnc/飞秋 都不涉及mac
    局域网
    连在一台交换机上的每台机器组成一个局域网
    交换机只认mac,第一次会把包转发到局域网内所有的设备,只有对应的才回答
    ARP:地址解析协议。交换机的广播和单播。
    局域网 – > 网关<-路由器->网关 —> 局域网
    IP地址
    ipv4:四位点分十进制
    192.168.12.78
    公网地址:需要我们自己申请购买的地址
    内网地址:保留字段
    192.168.X.X 内网地址 学校
    172.16.0.0 学校
    10.0.0.0- 10.255.255.255 公司
    特殊的ip地址
    127.0.0.1 本地回环地址 测试的时候用的
    ipconfig 查看自己的IP地址
    子网掩码
    用来判断两台机器在不在一个局域网内
    192.168.12.1
    11000000.10101000.00001100.00000001
    255.255.255.0
    11111111.11111111.11111111.00000000
    11000000.10101000.00001100.00000000
    192.168.12.0
    看子网掩码判断两个IP地址是不是在同一个局域网内
    ipv6
    0:0:0:0:0:0-

    ip/mac 确认机器
    端口 0-65535 确认机器上的具体应用程序

  2. osi协议

    osi7/5层协议
    应用层 表示层 会话层(三层合并成应用层) python 5 6 7层
    传输层 port 4层 四层路由器/交换机
    网络层 ip 3层 路由器 三层交换机
    数据链路层 mac 2层 网卡 二层交换机
    物理层 二进制串 1层

    tcp 和 udp 传输层
    tcp (语音聊天/视频聊天)- 线下缓存/qq远程控制
    需要先建立链接 然后才能通信
    占用连接/可靠(消息不会丢失)/实时性高/慢
    建立连接 - 三次握手
    全双共通信
    server SYN < - client
    server - > ACK SYN client
    server ACK < - client
    断开连接 - 四次挥手
    server FIN < - client
    server - > ACK client
    server - > FIN client
    server ACK < - client
    因为对方可能还有一些数据没传完,要双方都确定断开才断开
    udp (发消息)-在线播放视频
    不需要建立链接
    不占用连接/不可靠(消息因为网络不稳定而丢失)/快

  3. 简单的网络通信

    网络开发架构
    C/S架构 : 需要安装一下才能使用
    CLIENT
    SERVER
    可以离线使用/更安全
    B/S架构
    browser
    server
    不需要安装也能使用
    B/S也是C/S的一种
    统一用户的入口

    server端

    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1', 9000))
    sk.listen()
    while True:
        conn, addr = sk.accept()
        while True:
            send_m = input('>>>')
            conn.send(send_m.encode('utf-8'))
            if send_m.upper() == 'Q':
                break
            msg = conn.recv(1024)
            msg2 = msg.decode('utf-8')
            if msg2.upper() == 'Q':
                break
            print(msg2)
        conn.close()
    
    sk.close()
    

    client端

    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 9000))
    
    while True:
        msg = sk.recv(1024)
        msg2 = msg.decode('utf-8')
        if msg2.upper() == 'Q':
            break
        print(msg2)
        send_m = input('>>>')
        sk.send(send_m.encode('utf-8'))
        if send_m.upper() == 'Q':
            break
    
    sk.close()
    
  4. TCP文件传输

    server端

    import socket
    import json
    import struct
    
    # 接收
    sk = socket.socket()
    sk.bind(('127.0.0.1', 9000))
    sk.listen()
    
    conn, _ = sk.accept()
    blen = conn.recv(4)
    blen = struct.unpack('i', blen)
    msg = conn.recv(blen[0]).decode('utf-8')
    msg = json.loads(msg)
    # print(msg)
    with open(msg['filename'], mode='wb') as f:
        while msg['filesize'] > 0:
            content = conn.recv(1024)
            msg['filesize'] -= 1024
            f.write(content)
    
    conn.close()
    sk.close()
    

    client端

    import socket
    import os
    import json
    import struct
    
    # 发送
    sk = socket.socket()
    sk.connect(('127.0.0.1', 9000))
    
    # 文件名/文件大小
    abs_path = r'C:\Users\libo\Downloads\大圣换肤盒子v1.7 (1).exe'
    filename = os.path.basename(abs_path)
    filesize = os.path.getsize(abs_path)
    dic = {
          
          'filename': filename, 'filesize': filesize}
    str_dic = json.dumps(dic)
    blen = struct.pack('i', len(str_dic))
    sk.send(blen)
    sk.send(str_dic.encode('utf-8'))
    
    with open(abs_path, mode='rb') as f:
        while filesize > 0:
            content = f.read(1024)
            filesize -= len(content)
            sk.send(content)
    
    
    sk.close()
    
  5. UDP文件的传输

    server端

    import socket
    
    sk = socket.socket(type=socket.SOCK_DGRAM)  # UDP 协议
    sk.bind(('127.0.0.1', 9000))
    
    msg, addr = sk.recvfrom(1024)
    print(msg)
    sk.sendto(b'recv', addr)
    

    client端

    import socket
    
    sk = socket.socket(type=socket.SOCK_DGRAM)  # UDP 协议
    
    server = ('127.0.0.1', 9000)
    sk.sendto(b'info', server)
    
    msg = sk.recv(1024)
    print(msg)
    
  6. 粘包现象

    连续发送的两条消息,成为了一条消息发送过去
    发送消息 缓存机制 不一一发 浪费时间
    可能发生在 发送端 和 接收端
    粘包现象只发生在TCP协议中, 因为tcp多条消息之间没有边界
    发送端:两条消息很短,发送时间间隔也很短
    接收端:多条消息由于没有及时接收,而在接收方的缓存短堆在一起导致的粘包
    导致粘包的本质:设置边界。你发多少,我就接多少。
    做一个自定义长度协议
    宪法一个长度,我们规定长度的为4个字节
    然后对面接收4个字节,把长度得到, 然后接收固定长度的数据

    server端

    import struct
    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1', 9000))
    sk.listen()
    
    conn, addr = sk.accept()
    msg1 = input('...').encode('utf-8')
    msg2 = input('...').encode('utf-8')
    blen1 = struct.pack('i', len(msg1))
    conn.send(blen1)
    conn.send(msg1)
    blen2 = struct.pack('i', len(msg2))
    conn.send(blen2)
    conn.send(msg2)
    
    sk.close()
    # encode()  decode()  用什么方式编码 就用什么方式解码
    # zfil()自动在左边补零
    # # num = 6
    # # s = str(num)
    # # res = s.zfill(4)
    # # print(res)  # 0006
    # import struct
    # 
    # num = 12345
    # ret = struct.pack('i', num)
    # print(ret)  # b'90\x00\x00'
    # 
    # re = struct.unpack('i', ret)
    # print(re)  # (12345,)
    # struct.pack:自动把传入的num解析为四个字节的数据
    # struct.unpack:再解回来
    

    client端

    import socket
    import struct
    import time
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 9000))
    
    time.sleep(0.1)
    blen1 = sk.recv(4)
    blen1 = struct.unpack('i', blen1)
    msg1 = sk.recv(blen1[0])
    print(msg1.decode('utf-8'))
    blen2 = sk.recv(4)
    blen2 = struct.unpack('i', blen2)
    msg2 = sk.recv(blen2[0])
    print(msg2.decode('utf-8'))
    
    sk.close()
    
  7. socketserver模块

    socket 底层
    socketserver 基于socket完成的 封装度高

    tcp协议的server端处理并发的客户端请求

    server.py

    import socketserver
    import time
    
    class Myserver(socketserver.BaseRequestHandler):
        def handle(self):
            conn = self.request
            while True:
                try:
                    content = conn.recv(1024).decode('utf-8')
                    conn.send(content.upper().encode('utf-8'))
                    time.sleep(0.5)
                except ConnectionResetError:
                    break
    
    
    server = socketserver.ThreadingTCPServer(('127.0.0.1', 9000), Myserver)
    server.serve_forever()
    

    client.py

    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 9000))
    
    while True:
        sk.send(b'hello')
        content = sk.recv(1024).decode('utf-8')
        print(content)
    

猜你喜欢

转载自blog.csdn.net/qq_31910669/article/details/109209865