zoukankan      html  css  js  c++  java
  • python-网络编程

    1.osi五层协议

    # 应用层
        # 传输层
            # tcp协议 : 效率低 面向连接可靠全双工的通信
                # 三次握手
                    # 客户端向服务器端发送syn请求,
                    # 服务端向客户端回复ack并发送syn请求,
                    # 客户端接收到请求之后再回复ack表示建立连接
                    # 由客户端的connect + 服务端的accept
                # 四次挥手
                    # 客户端向服务端发送fin请求,
                    # 服务端回复ack确认
                    # 服务端向客户端发送fin请求,
                    # 客户端回复ack确认
                    # 有客户端的close和服务端的close
            # udp协议 : 效率高 无连接的不可靠
            # 四层交换机 四层路由器
        # 网络层
            # ip协议(ipv4 ipv6)
            # 路由器三层交换机
        # 数据链路层
            # arp协议 地址解析协议 通过ip找到mac地址
            # 交换机网卡 : 单播 广播 组播
        # 物理层

    2  b/s c/s架构

     C/S   client server
     B/S   browser server

    3.tcp协议和udp协议

    TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。
    
    UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。
    
    我知道说这些你们也不懂,直接上图。

    3.简单的tcp网络通信

    #server服务端
    
    import socket  #炒茄子
    
    sk = socket.socket()          # 创建一个server端的对象
    sk.bind(('127.0.0.1',9001))  # 给server端绑定一个地址 ,可以写自己的IP地址
    sk.listen()                   # 开始监听(可以接收)客户端给我的连接了
    
    conn,addr = sk.accept()  # 建立连接 conn是连接,ADDR是地址,也可以不写这个变量
    conn.send(b'hello')   #联上后,进行通信
    msg = conn.recv(1024) #1024 表示最多接收1024个字
    print(msg)
    conn.close()     # 关闭连接
    
    sk.close()  #关掉服务
    client客户端
    import socket
    
    sk = socket.socket()   #实例化对象
    sk.connect(('127.0.0.1',9001))  #联接server端
    
    
    msg = sk.recv(1024)   #1024 表示最多接收1024个字
    print(msg)
    sk.send(b'byebye')
    
    sk.close()

     5.tcp简单多人通信

    #server端
    
    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1',9001))   # 申请操作系统的资源
    sk.listen()
    
    while True:  # 为了和多个客户端进行握手
        conn,addr = sk.accept() # 能够和多个客户端进行握手了
        print('conn : ',conn)
        while True:
            send_msg = input('>>>')
            conn.send(send_msg.encode('utf-8'))
            if send_msg.upper() == 'Q':
                break
            msg = conn.recv(1024).decode('utf-8')
            if msg.upper() == 'Q': break
            print(msg)
        conn.close()    # 挥手 断开连接
    
    sk.close()      # 归还申请的操作系统的资源
    #client
    
    # _*_ coding : UTF-8 _*_
    import socket
    sk = socket.socket()
    sk.connect(('127.0.0.1',9001))
    
    
    while True:
        msg = sk.recv(1024)  #����
        msg2 = msg.decode('utf-8')
        if msg2.upper() == 'Q':break
        print(msg,msg2)
        send_msg = input('>>>')
        sk.send(send_msg.encode('utf-8'))
        if send_msg.upper() == 'Q':
                break
    sk.close()

    6.简单的udp协议

    #server
    
    import socket
    sk = socket.socket(type= socket.SOCK_DGRAM)
    
    sk.bind(('127.0.0.1',9000))
    
    msg,addr = sk.recvfrom(1024)
    print(msg)
    
    sk.sendto(b'2',addr)
    # client
    
    import  socket
    sk = socket.socket(type=socket.SOCK_DGRAM)
    
    server = ('127.0.0.1',9000)
    
    sk.sendto(b'1',server)
    
    msg = sk.recv(1024)
    print(msg)

    7.多人的udp协议

    #server
    
    import socket
    #udp可以跟任意人联接.
    sk = socket.socket(type = socket.SOCK_DGRAM) #udp协议  实例化对象
    sk.bind(('127.0.0.1',9001))   #联接
    while True:
        msg,addr= sk.recvfrom(1024)  #接收
        print(msg.decode('utf-8'))
        msg = input('>>>')
        sk.sendto(msg.encode('utf-8'),addr)  #发送
    
    
    #server不能接收Q退出..不然就不能跟别人联接了..只需要客户端退出就行了
    #client
    
    import socket
    
    sk = socket.socket(type=socket.SOCK_DGRAM)
    server = ('127.0.0.1',9001)
    while True:
        msg = input('>>>')
        if msg.upper() == 'Q':break
        sk.sendto(msg.encode('utf-8'),server)   # 发送
        msg = sk.recv(1024).decode('utf-8')  #收到
        if msg.upper() == 'Q':break
        print(msg)

     8.黏包    struct 模块

    同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接收到之前执行的另外一部分结果,这种显现就是黏包。

    import struct
    
    num1 = 129469649
    num2 = 123
    num3 = 8
    
    ret1 = struct.pack('i',num1) #把一个整数pack
    print(len(ret1))
    ret2 = struct.pack('i',num2)
    print(len(ret2))
    ret3 = struct.pack('i',num3)
    print(len(ret3))
    
    print(struct.unpack('i',ret1))  #转为原来数值129469649
    print(struct.unpack('i', ret2))
    print(struct.unpack('i', ret3))

    8.1 tcp协议的现象

    #server端
    
    import struct
    import socket
    
    sk = socket.socket()
    sk.bind(('127.0.0.1',9001))
    sk.listen()
    
    conn,addr = sk.accept()
    msg1 = input('>>>').encode()
    msg2 = input('>>>').encode()
    # num = str()  # '10001'
    # ret = num.zfill(4)    # '0006' 补0.向左补4个0
    # conn.send(ret.encode('utf-8'))
    blen = struct.pack('i',len(msg1))
    conn.send(blen)
    conn.send(msg1)
    conn.send(msg2)
    conn.close()
    sk.close()
    
    # 粘包现象
    # 只出现在tcp协议中,因为tcp协议 多条消息之间没有边界,并且还有一大堆优化算法
    # 发送端 : 两条消息都很短,发送的间隔时间也非常短
    # 接收端 : 多条消息由于没有及时接收,而在接收方的缓存短堆在一起导致的粘包
    
    # 解决粘包问题的本质 :设置边界
    
    
    # server端
    # 1.先计算要发送的数据的长度
    # 通过struct模块把长度转换成固定的4字节
    # 发送4个字节的长度
    # 发送内容....
    #client端
    
    import time
    import struct
    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1',9001))
    # length = int(sk.recv(4).decode('utf-8'))
    length = sk.recv(4)
    length = struct.unpack('i',length)[0] #返回的是元组
    msg1 = sk.recv(length)
    msg2 = sk.recv(1024)
    print(msg1.decode('utf-8'))
    print(msg2.decode('utf-8'))
    
    sk.close()

     9.基于udp 协议的多人聊天  自动识别用户,

    server端
    
    import socket
    friend ={'小明':34,'小王':32}
    sk = socket.socket(type=socket.SOCK_DGRAM)
    sk.bind(('127.0.0.1',9000))
    
    while True:
        mag,addr = sk.recvfrom(1024)
    
        mag = (mag.decode('utf-8'))
        name,message = mag.split('|')
        print('33[1;%sm;%s:%s33[0m'%(friend.get(name,30),name,message))
    
        mag = input('<<<')
        sk.sendto(mag.encode('utf-8'),addr)
    client端
    
    import  socket
    name = '小明'
    
    while True:
        sk = socket.socket(type=socket.SOCK_DGRAM)
        server = (('127.0.0.1',9000))
    
        mag = input('<<<')
        if mag.upper() =='Q':break
        mag = '%s|%s'%(name,mag)
        sk.sendto(mag.encode('utf-8'),server)
        mag = sk.recv(1024).decode('utf-8')
        if mag.upper() == 'Q': break
        print(mag)

     10.用tcp实现接收发送小文件和大文件的功能

    servet端
    #接收
    
    import  socket
    import  json
    import struct
    
    sk = socket.socket()
    # sk.bind(('127.0.0.1'),9000)
    sk.bind(('127.0.0.1',7003))
    sk.listen()
    
    conn,addr = sk.accept()
    #为了解决粘包现象,先接收4个字节.
    # mag = conn.recv(1024).decode('utf-8')
    mag = conn.recv(4)
    dic_len = struct.unpack('i',mag)[0]
    dic_len = conn.recv(dic_len).decode('utf-8')
    
    mag = json.loads(dic_len)
    
    with open(mag['filename'],mode='wb') as f:
        while mag['filesize'] > 0:
            content = conn.recv(1024) #先接1024字节
            mag['filesize'] -= len(content)  #在接剩余的
    
            f.write(content)
    
    conn.close()
    sk.close()
    client端
    
    mport  socket
    import json
    import os
    import struct
    sk = socket.socket()
    sk.connect(('127.0.0.1',7003))
    
    #文件/文件名
    addr_path = r'E:zlday07 课上视频day07 课上视频4 python fullstack s22 day07 编码的进阶【it资源社区www.it0365.com】.mp4'
    filename = os.path.basename(addr_path) #文件
    filesize = os.path.getsize(addr_path)  #文件大小
    dic = {'filename':filename,'filesize':filesize}
    new_mag =json.dumps(dic)  #json传字符串
    new_mag = new_mag.encode('utf-8')
    mlab = struct.pack('i',len(new_mag))
    sk.send(mlab)   ## 4个字节 表示字典转成字节之后的长度
    sk.send(new_mag)  ## 具体的字典数据
    
    
    
    #如要传大文件的话.需要减去大小
    #还有为了防止粘包..
    with open(addr_path,mode='rb') as f:
        while filesize>0:
            content = f.read(1024) #先读1024个字节
            filesize -= len(content)  #总字节减去传送过去的
            sk.send(content)
    
    sk.close()

     11.检验客户端的合法性

    server端
    
    import  os
    import socket
    import hashlib
    
    
    secket_key = b'zeng'
    
    sk = socket.socket()
    # sk.bind(('127.0.0.1',9001))
    sk.bind(('127.0.0.1',7005))
    sk.listen()
    
    conn,addr = sk.accept()
    
    # 创建一个随机的字符串
    ret = os.urandom(32)
    
    # 发送随机字符串
    conn.send(ret)
    
    # 根据发送的字符串 + secrete key 进行摘要
    sha = hashlib.sha1(secket_key)
    sha.update(ret)
    res = sha.hexdigest()  #获取密文
    # 等待接收客户端的摘要结果
    res_new = conn.recv(1024).decode('utf-8')
    # 做比对
    if res_new == res:
        print('合法的')
       # 如果一致,就显示是合法的客户端
        # 并可以继续操作
        conn.send(b'ok')
    else:
        conn.close()
        # 如果不一致,应立即关闭连接
    client端
    
    
    import socket
    import hashlib
    
    secket_key = b'zeng'
    
    
    sk = socket.socket()
    # sk.connect(('127.0.0.1',9001))
    sk.connect(('127.0.0.1',7001))
    
    
    
    # 接收客户端发送的随机字符串
    ret = sk.recv(32)
    
    # 根据发送的字符串 + secret key 进行摘要
    sha=hashlib.sha1(secket_key)  #密钥
    sha.update(ret)  #发送
    res = sha.hexdigest()  #获取密文
    
    # 摘要结果发送回server端
    sk.send(res.encode('utf-8'))
    # 继续和server端进行通信
    mag = sk.recv(1024)
    print(mag)

     12.socketserver  ,后续所有的server端.都用这模块.需要记住这代码.client端不变

    以后用tcp时.需要建立目录.目录为socketserver .在此目录下,还需要建立server和client
    #server
    
    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(1)
                except ConnectionRefusedError:
                    break
    
    
    
    server = socketserver.ThreadingTCPServer(('127.0.0.1',7004),Myserver)
    server.serve_forever()
    #client
    
    import socket
    
    sk=socket.socket()
    sk.connect(('127.0.0.1',7004))
    
    while True:
    
        sk.send(b'hehe')
        mag = sk.recv(1024).decode('utf-8')
        print(con,mag)
    
    
  • 相关阅读:
    servlet-响应信息
    社会学系列:《乡土中国》读书笔记
    文学系列:《叶之震颤》读书笔记
    《娱乐至死》读书笔记
    畅销书系列:《引爆点》、《异类》、《从0到1》
    大学《管理学》教材笔记
    心理学系列:《乌合之众》读书笔记
    心理学系列:《我们内心的冲突》、《亲密关系》、《犯罪心理学》、《态度改变与社会影响》读书笔记
    政史系列:《社会契约论》读书笔记
    音乐系列:2018年滚石琴行木吉他学习笔记
  • 原文地址:https://www.cnblogs.com/zengluo/p/12862153.html
Copyright © 2011-2022 走看看