zoukankan      html  css  js  c++  java
  • Django(一):web服务端实例

    1. 不完善的web服务端实例
    2. 根据不同的路径返回不同的内容
    3. 返回html页面
    4. 总结
     
     
     

    1.不完善的web服务端实例
    a.尝试第一次连接:
    #写客户端
    import socket
    #创建一个scoket实例对象
    sk = socket.socket()
    #绑定ip地址和端口
    sk.bind(('127.0.0.1',8000))
    #监听
    sk.listen()
    #写一个死循环,一直等待客户端来连接
    while 1:
       #获取与客户端的连接
       conn, _ = sk.accept()
       #接收客户端发来的消息
       conn.recv(8888)
       #给客户端回复消息
       conn.send(b'successful')
       #关闭
       conn.close()
       sk.close()
    写好之后,运行。在浏览器中输入127.0.0.1:8000回车,发现该网页无法正常运作,第一次尝试失败。
    b.为了发现错误原因,将接收到客户端消息打印出来,再次运行
    data = conn.recv(8888)
    print(data)
    返回以下错误:
    b'GET / HTTP/1.1 Host: 127.0.0.1:8001 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 '
    整理以上错误信息,得到:
    '
    GET / HTTP/1.1    请求行
    Host:127.0.0.1:8001    请求头
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9
    '    没有请求数据
    原因分析:浏览器给我发的消息我收到了,但是我回复的东西浏览器不认识(没有遵从浏览器的协议),因此出现了问题
    c.经过上述分析,加上以下内容,得到正常的显示
    conn.send(b'http/1.1 200 OK ')    #这里发送的是请求行,请求头部
    conn.send(b'successful!')    #这里发送的是请求数据
    #浏览器和服务端通信都要遵循一个HTTP协议
    关于HTTP协议:
    1.浏览器往服务端发的叫做 请求(request)
    请求的消息格式:
        请求方法 路径 HTTP/1.1
        k1:v1
        k2:v2
       
        请求数据
    2.服务端往浏览器发的叫做 响应(response)
    响应的消息格式:
        HTTP/1.1 状态码 状态描述符
        k1:v1
        k2:v2
       
        响应正文     <---html的内容
    调试:
    conn.send(b'http/1.1 200 OK content-type:text/html; charset=utf8 ')
    conn.send(b'<h1>successful<h1>')
    import socket
     
    sk = socket.socket()
    sk.bind(('127.0.0.1', 7777))
    sk.listen(5)
     
    while 1:
        conn, addr = sk.accept()
        print(conn, addr)
        data = conn.recv(1024)
        conn.send(b'HTTP/1.1 200 OK ')
        conn.send(b'<h1>hello world</h1>')
        conn.close()
     

    2.根据不同的路径返回不同的内容
    把收到的数据转成字符串格式:
    data_str = str(data, encoding='utf8')
    import socket
    #创建一个scoket实例对象
    sk = socket.socket()
    #绑定ip地址和端口
    sk.bind(('127.0.0.1',8001))
    #监听
    sk.listen()
    #写一个死循环,一直等待客户端来连接
    while 1:
       #获取与客户端的连接
       conn, _ = sk.accept()
       #接收客户端发来的消息
       data = conn.recv(8888)
       #把收到的数据转成字符串类型
       data_str = str(data, encoding='utf8')
       #用 去切割上面的字符串
       li = data_str.split(' ')
       #print(li[0])
       #按照空格切割上面的字符串
       li2 = li[0].split()
       path = li2[1]
       conn.send(b'http/1.1 200 OK content-type:text/html; charset=utf8 ')
       
       #根据不同的path返回不同的content
       if path == '/':
           conn.send(b'<h1>successful<h1>')
       elif path == '/123/':
           conn.send(b'<h1>nothing!<h1>')
       else:
           conn.send(b'<h1>404! not found!<h1>')
       #关闭
       conn.close()
       sk.close()
    优化上述代码:
    if path == '/111/':
       response = b'<h1>successful<h1>'
    elif path == '/123/':
       response = b'<h1>nothing!<h1>'
    else:
       response = b'<h1>404! not found!<h1>'
     
    conn.send(response)
    再次优化,写入函数:
    def func1():
        ret = 'hello {}'.format(url)
        return bytes(ret, encoding='utf8')
    def func2():
        return b'<h1>nothing!<h1>'
     
    if path == '/111/':
       response = func1()
    elif path == '/123/':
       response = func2()
    else:
       response = b'<h1>404! not found!<h1>'
     
    conn.send(response)
    去掉if条件:
    """
    完善的web服务端示例
    函数版根据不同的路径返回不同的内容
    进阶函数版 不写if判断了,用url名字去找对应的函数名
    """
     
    import socket
     
    # 生成socket实例对象
    sk = socket.socket()
    # 绑定IP和端口
    sk.bind(("127.0.0.1", 8001))
    # 监听
    sk.listen()
     
    # 定义一个处理/yimi/的函数
    def yimi(url):
       ret = 'hello {}'.format(url)
       return bytes(ret, encoding="utf-8")
     
     
    # 定义一个处理/xiaohei/的函数
    def xiaohei(url):
       ret = 'hello {}'.format(url)
       return bytes(ret, encoding="utf-8")
     
     
    # 定义一个专门用来处理404的函数
    def f404(url):
       ret = "你访问的这个{} 找不到".format(url)
       return bytes(ret, encoding="utf-8")
     
     
    url_func = [
       ("/yimi/", yimi),
       ("/xiaohei/", xiaohei),
    ]
     
     
    # 写一个死循环,一直等待客户端来连我
    while 1:
       # 获取与客户端的连接
       conn, _ = sk.accept()
       # 接收客户端发来消息
       data = conn.recv(8096)
       # 把收到的数据转成字符串类型
       data_str = str(data, encoding="utf-8")  # bytes("str", enconding="utf-8")
       # print(data_str)
       # 用 去切割上面的字符串
       l1 = data_str.split(" ")
       # print(l1[0])
       # 按照空格切割上面的字符串
       l2 = l1[0].split()
       url = l2[1]
       # 给客户端回复消息
       conn.send(b'http/1.1 200 OK content-type:text/html; charset=utf-8 ')
       # 想让浏览器在页面上显示出来的内容都是响应正文
     
       # 根据不同的url返回不同的内容
       # 去url_func里面找对应关系
      for i in url_func:
           if i[0] == url:
               func = i[1]
               break
       # 找不到对应关系就默认执行f404函数
       else:
           func = f404
       # 拿到函数的执行结果
       response = func(url)
       # 将函数返回的结果发送给浏览器
       conn.send(response)
       # 关闭连接
       conn.close()
     
     
     
     
     

    3.返回html页面
    """
    完善的web服务端示例
    函数版根据不同的路径返回不同的内容
    进阶函数版 不写if判断了,用url名字去找对应的函数名
    """
     
    import socket
     
    # 生成socket实例对象
    sk = socket.socket()
    # 绑定IP和端口
    sk.bind(("127.0.0.1", 8001))
    # 监听
    sk.listen()
     
    # 定义一个处理/yimi/的函数
    def yimi(url):
       with open('html1.html','rb') as f:
           ret = f.read()
       return ret
     
     
    # 定义一个处理/xiaohei/的函数
    def xiaohei(url):
       with open('html2.html','rb') as f:
           ret = f.read()
       return ret
     
     
    # 定义一个专门用来处理404的函数
    def f404(url):
       ret = "你访问的这个{} 找不到".format(url)
       return bytes(ret, encoding="utf-8")
     
     
    url_func = [
       ("/yimi/", yimi),
       ("/xiaohei/", xiaohei),
    ]
     
     
    # 写一个死循环,一直等待客户端来连我
    while 1:
       # 获取与客户端的连接
       conn, _ = sk.accept()
       # 接收客户端发来消息
       data = conn.recv(8096)
       # 把收到的数据转成字符串类型
       data_str = str(data, encoding="utf-8")  # bytes("str", enconding="utf-8")
       # print(data_str)
       # 用 去切割上面的字符串
       l1 = data_str.split(" ")
       # print(l1[0])
       # 按照空格切割上面的字符串
       l2 = l1[0].split()
       url = l2[1]
       # 给客户端回复消息
       conn.send(b'http/1.1 200 OK content-type:text/html; charset=utf-8 ')
       # 想让浏览器在页面上显示出来的内容都是响应正文
     
       # 根据不同的url返回不同的内容
       # 去url_func里面找对应关系
       for i in url_func:
           if i[0] == url:
               func = i[1]
               break
       # 找不到对应关系就默认执行f404函数
       else:
           func = f404
       # 拿到函数的执行结果
       response = func(url)
       # 将函数返回的结果发送给浏览器
       conn.send(response)
       # 关闭连接
       conn.close()
    返回动态的html页面
    动态的html页面本质上都是字符串在服务端的替换。
    #插入动态事件戳
    def yimi(url):
       with open('html1.html','rb') as f:
           ret = f.read()
        import time
        ret2 = ret.replace('@@xx@@', str(time.time()))
       return bytes(ret2, encoding='utf-8')
     

    4.总结:
    1. web框架的本质:
               socket服务端  与 浏览器的通信
     2. socket服务端功能划分:
               a. 负责与浏览器收发消息(socket通信)  --> wsgiref/uWsgi/gunicorn...
               b. 根据用户访问不同的路径执行不同的函数
               c. 从HTML读取出内容,并且完成字符串的替换  --> jinja2(模板语言)
    3. Python中 Web框架的分类:           
        1. 按上面三个功能划分:
                   1. 框架自带a,b,c                 --> Tornado
                   2. 框架自带b和c,使用第三方的a    --> Django
                   3. 框架自带b,使用第三方的a和c    --> Flask
        2. 按另一个维度来划分:
                   1. Django   --> 大而全(你做一个网站能用到的它都有)
                   2. 其他     --> Flask 轻量级
     
     
     
     
     
     
     
  • 相关阅读:
    MySQL++:(转)mybatis 常用 jdbcType数据类型
    CF1556F Sports Betting (状压枚举子集DP)
    ICPC Greater New York Region 2020 F
    post方式实现导出/下载文件
    自定义一个v-if
    在vue项目中引用element-ui时 让el-input 获取焦点的方法
    element-select当下拉框数据过多使用懒加载
    vue强制刷新组件更新数据的方式
    .net core efcore dbfirst(sqlserver,mysql,oracle,postgresql)
    camunda安装配置mysql以及整合springboot
  • 原文地址:https://www.cnblogs.com/changwoo/p/9568480.html
Copyright © 2011-2022 走看看