我的编程空间,编程开发者的网络收藏夹
学习永远不晚

粘包、阻塞与非阻塞、验证客户端的合法性

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

粘包、阻塞与非阻塞、验证客户端的合法性

1.1 tcp协议的粘包现象

tcp协议传输数据存在粘包现象,udp协议不存在粘包协议。

1.1.1 什么是粘包现象

  • 1.发生在发送端的粘包

    由于两个数据的发送时间间隔短+数据的长度小,所以由tcp协议的优化机制将两条信息作为一条信息发送出去了,是为了减少tcp协议中的“确认收到”的网络延迟时间

  • 2.在接收端的粘包

    由于tcp协议中所传输的数据无边界,所以来不及接收的多条数据会在接收方的内核的缓存端黏在一起

  • 3.本质: 接收信息的边界不清晰

1.1.2 解决粘包问题

  • 1.自定义协议1:

    • a.首先发送报头

      报头长度4个字节
      内容是 即将发送的报文的字节长度
      struct模块

      • struck.pack 能够把所有的数字都固定的转换成4字节
    • b.再发送报文

  • 2.自定义协议2

    专门用来做文件发送的协议

    • 先发送报头字典的字节长度
    • 再发送字典(字典中包含文件的名字、大小。。。)
    • 再发送文件的内容

1.2 tcp协议和udp协议的特点

  • tcp : 是一个面向连接的,流式的,可靠的,慢的,全双工通信(三次握手、四次挥手)
    如:邮件 / 文件/ http / web
  • udp : 是一个面向数据报的,无连接的,不可靠,快的,能完成一对一、一对多、多对一、多对多的高效通讯协议
    如:即时聊天工具 / 视频的在线观看

1.3 三次握手 / 四次挥手

  • 1.三次握手

    • server端:accept接受过程中等待客户端的连接
    • connect客户端发起一个SYN链接请求
    • 如果收到了server端响应ACK的同时还会再收到一个由server端发来的SYN链接请求
    • client端进行回复ACK之后,就建立起了一个tcp协议的链接

    三次握手的过程在代码中是由accept和connect共同完成的,具体的细节再socket中没有体现出来

  • 2.四次挥手

    • server和client端对应的在代码中都有close方法
    • 每一端发起的close操作都是一次FIN的断开请求,得到'断开确认ACK'之后,就可以结束一端的数据发送。
    • 如果两端都发起close,那么就是两次请求和两次回复,一共是四次操作,可以结束两端的数据发送,表示链接断开了

2.1 阻塞与非阻塞

2.1 io模型

io模型种类:

  • 阻塞io模型、非阻塞io模型、事件驱动io、io多路复用、异步io模型

2.2 socket的非阻塞io模型

server端同时与多个client客户端之间的聊天:

  • socket的非阻塞io模型 + io多路复用实现的

    虽然非阻塞,提高了CPU的利用率,但是耗费CPU做了很多无用功

# server.py
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.setblocking(False) # 非阻塞,setblocking()的参数为False时,表示非阻塞,如果参数不写,默认为True。
sk.listen()

conn_l = []
del_l = []
while True:
    try:
        conn,addr = sk.accept()   # 阻塞,直到有一个客户端来连我
        print(conn)
        conn_l.append(conn)
    except BlockingIOError:
        for c in conn_l:
            try:
                msg = c.recv(1024).decode('utf-8')
                if not msg:
                    del_l.append(c)
                    continue
                print('-->',[msg])
                c.send(msg.upper().encode('utf-8'))
            except BlockingIOError:pass
        for c in del_l:
            conn_l.remove(c)
        del_l.clear()
sk.close()

# client.py
import time
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9000))
for i in range(30):
    sk.send(b'zhangsan')
    msg = sk.recv(1024)
    print(msg)
    time.sleep(0.2)
sk.close()

2.3 socketserver模块

socketserver模块解决了socket的阻塞问题,直接实现tcp协议可并发的server端

# server.py
import socketserver

class Myserver(socketserver.BaseRequestHandler):
    def handle(self):  # 自动触发了handle方法,并且self.request == conn
        msg = self.request.recv(1024).decode('utf-8')
        self.request.send('1'.encode('utf-8'))
        msg = self.request.recv(1024).decode('utf-8')
        self.request.send('2'.encode('utf-8'))
        msg = self.request.recv(1024).decode('utf-8')
        self.request.send('3'.encode('utf-8'))

server = socketserver.ThreadingTCPServer(('127.0.0.1',9000),Myserver)
server.serve_forever()

# client.py
import socket
import time
sk = socket.socket()
sk.connect(('127.0.0.1',9000))
for i in range(3):
    sk.send(b'hello,yuan')
    msg = sk.recv(1024)
    print(msg)
    time.sleep(1)

sk.close()

3. 验证客户端的合法性

  • 客户端是提供给 用户使用的 —— 登陆验证
    你的用户 就能看到你的client端源码了,用户就不需要自己写客户端了

  • 客户端是提供给 机器使用的 —— 验证客户端的合法性

    防止非法用户进入服务端窃取内部重要信息

    # server.py
    import os
    import hashlib
    import socket
    
    def get_md5(secret_key,randseq):
        md5 = hashlib.md5(secret_key)
        md5.update(randseq)
        res = md5.hexdigest()
        return res
    
    def chat(conn):
        while True:
            msg = conn.recv(1024).decode('utf-8')
            print(msg)
            conn.send(msg.upper().encode('utf-8'))
    
    sk = socket.socket()
    sk.bind(('127.0.0.1',9000))
    sk.listen()
    
    secret_key = b'names'
    while True:
        conn,addr = sk.accept()
        randseq = os.urandom(32)
        conn.send(randseq)
        md5code = get_md5(secret_key,randseq)
        ret = conn.recv(32).decode('utf-8')
        print(ret)
        if ret == md5code:
            print('是合法的客户端')
            chat(conn)
        else:
            print('不是合法的客户端')
            conn.close()
    sk.close()
    
    # client.py
    import hashlib
    import socket
    import time
    
    def get_md5(secret_key,randseq):
        md5 = hashlib.md5(secret_key)
        md5.update(randseq)
        res = md5.hexdigest()
        return res
    def chat(sk):
        while True:
            sk.send(b'hello')
            msg = sk.recv(1024).decode('utf-8')
            print(msg)
            time.sleep(0.5)
    sk = socket.socket()
    sk.connect(('127.0.0.1',9000))
    
    secret_key = b'names'
    randseq = sk.recv(32)
    md5code = get_md5(secret_key,randseq)
    sk.send(md5code.encode('utf-8'))
    chat(sk)
    
    sk.close()

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

粘包、阻塞与非阻塞、验证客户端的合法性

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

粘包、阻塞与非阻塞、验证客户端的合法性

1.1 tcp协议的粘包现象tcp协议传输数据存在粘包现象,udp协议不存在粘包协议。1.1.1 什么是粘包现象1.发生在发送端的粘包由于两个数据的发送时间间隔短+数据的长度小,所以由tcp协议的优化机制将两条信息作为一条信息发送出去了,是
2023-01-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录