jovanywang

jovanywang 查看完整档案

杭州编辑安徽财经大学  |  计算机科学与技术 编辑AL  |  分布式系统开发 编辑 jovany.wang 编辑
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

jovanywang 关注了标签 · 2019-11-11

分布式

分布式计算是一门计算机科学,它研究如何把一个需要非常巨大的计算能力才能解决的问题分成许多小的部分,然后把这些部分分配给许多计算机进行处理,最后把这些计算结果综合起来得到最终的结果。

关注 316

jovanywang 回答了问题 · 2018-01-25

解决对于网上大多数判断链表是否有环的思路提出疑问

你并不知道环的起始在那个位置,并不是head开始就形成环的。

关注 3 回答 2

jovanywang 回答了问题 · 2018-01-25

解决大型项目中的字符串,连接服务器的地址等都是如何组织的?

配置文件,和安卓原理都一样的,只不过没有框架帮你做好你只需填一下就可以

关注 3 回答 3

jovanywang 赞了文章 · 2018-01-23

基于 oracle 的 flask 项目(二)——用户登录

flask 相对于很多国企的 oracle 数据库而言,是比较新的,因此很多古老的设计并不一定适合较新的 flask 的标准,但作为后来者,你得向前兼容,你得适应需求。
本章内容就来解释一下上一章——基于 oracle 的 flask 项目(一)——配置项目留下的彩蛋——数据库到底留下了什么样的坑?

项目描述

绝对大多数的网站需要管理功能的,这个功能是不对外开放,需要有权限的用户登录后才能操作的。这个登录功能对于大牛来说,肯定是操作 session, cookies 了,其实不必这么麻烦, flask-login 插件可以解决你的登录问题,但是要注意一些小细节,本章内容就是来讨论一些细节内容。

  • 本章主要帮你解决你的项目的 DBA 管理员没有给你设置主键,主键也不是 id 的问题。

创建登录模板

  1. 在 app/templates/show 目录下新建一个 login.html 页面。
  2. 同时,对模板进行分割,创建文件夹 common , 将主模板 base.html,提示模板 alert.thml 、头文件 header.html,侧边栏 sidebar.html 等共用文件,都放入该文件夹。
  3. 其中使用到一些 css 和 js 的内容,需要放在蓝图文件夹下的 static 文件夹里面。
  4. 个性化你的 web 主页,设置你的 index.html。

使用数据库及映射类

使用数据库及映射类的时候,需要用到 sqlalchemy 第三方库, flask 也提供了一个封装好的插件 flask-sqlalchemy ,拿来使用即可。但是要使用 sqlalchemy, 在创建映射类的时候,必须得设置主键。但是很多前辈的 DBA 们的眼里可是没有 flask 的概念的,很多表是没有设置主键的,我们该怎么办?

答:先对 DBA 管理员翻个白眼,然后自己默默的做事吧。还能怎么办呢!!!
找个具有唯一性,不重复的字段,在创建映射类的时候,把该字段定义为主键。也就是说,不管数据库中是否定义了主键,只要映射类种定义了即可。
当然,有的同学会说,我们找不到具有唯一性,不重复的字段,该怎么办?那就继续给你的 DBA 管理员翻白眼呗,翻到他清醒为止。

还好,我的项目中的数据库还是有主键的,无需在映射类种,建立虚假的主键。

内容不在赘述,请参加代码。

设置 flask-login

初始化 flask-login

app/__init__.py 里进行设置:

login_manager = LoginManager()
login_manager.session_protection = 'strong' # 可以设置None,'basic','strong'  以提供不同的安全等级,一般设置strong,如果发现异常会登出用户。
login_manager.login_view = 'show.login' # 这里填写你的登陆界面的路由

def create_app(config_name):
    """ 使用工厂函数初始化程序实例"""
    ....
    login_manager.init_app(app=app)

很多时候,我们会遇到 remember_me 无效的情况,请将 login_manager.session_protection 设置成 basic 试试。

详细设置请看程序注释及[源代码02]()。

配置 flask-login

models.py 中的用户映射类继承 flask_login 中的 UserMixin 类,该类实现了 4 个用户方法,基本上能够满足用户登录的需求,如需其它的用户方法,可自行定义。

class OusiStaff(UserMixin, db.Model):
    __tablename__ = 'ousi_staff'
    sid = db.Column(db.Integer, primary_key=True)
    department = db.Column(db.String(8))
    name = db.Column(db.String(8))
    password = db.Column(db.String(8))
    phone = db.Column(db.String(11))
    role = db.Column(db.String(8))

    def is_admin(self): # 自行定义的方法,用于权限判断
        return self.role == 'admin'


class AnonymousUser(AnonymousUserMixin):
    '''
    继承至该类的用户模型 将作为未登陆时的用户模型,可以保持代码的一致性。
    '''
    def is_admin(self): # 自行定义的方法,用于权限判断
        return False


login_manager.anonymous_user = AnonymousUser

实现用户的回调函数

也是在 models.py 里实现:

@login_manager.user_loader
def load_user(user_id):
    return OusiStaff.query.get(int(user_id))

此处,不详细讲解,仅仅是实现了一个回调用户的函数。

使用登录权限限制

既然使用了登录功能,那么肯定是有些内容不能让未登录的用户观看,这就需要在试图函数定义的时候加上一个 login_required 装饰器了。

这个功能的实现很简单,在 views.py 里进行修改:

...
from flask_login import login_required, login_user, logout_user
...

@show.route('/', methods = ['GET', 'POST'])
@show.route('/index', methods = ['GET', 'POST'])
@login_required
def index():

    return render_template('show/index.html')

至此,你可以测试自己的项目了。


问题

NotImplementedError: No 'id' attribute - override 'get_id' 错误的问题


...

bug 如影随从。这是你遇到的第一个错误。你会发现登录之后马上就报这个错误。那么兵来将挡水来土掩,找到问题,解决问题。

首先,报错的地点显示是我们自己的代码中的 login_user,而真正报错的地点是 minins.py 源码中的 39 行,那么这一行的真面目是什么呢?

def get_id(self):
    try:
        return text_type(self.id)
    except AttributeError:
        raise NotImplementedError('No `id` attribute - override `get_id`')

你可以清晰的看到,这个 get_id 函数的返回值是 return text_type(self.id) 是当前用户的 id。那么我们的 models.py 中定义的 OusiStaff 类有 id 这个字段吗没有。只有一个作为主键的 sid 字段。看到这里,估计你会对以前的 DBA 管理员问候很多声了,OK,稍安勿躁,问候了之后还得解决问题。很直观的解决方法是,修改源码,将 return text_type(self.id) 修改为 return text_type(self.sid)。但是这样的方法很危险,很造成一些其它项目的兼容性问题。显得这个程序员很 low。

再次我们用一种更好、更优雅的方法来解决。在 models.py 文件内的 OusiStaff 映射类中添加如下内容:

class OusiStaff(UserMixin, db.Model):
    ...
    ...
    
    @property
    def id(self):
        return self.sid

增加一个 id 属性。解决问题。

神奇的 @property。 彩蛋就如此简单的被解决。

打开页面,显示正常。

源码下载

下节更精彩,我们将讲解使用 flask-sqlalchemy 来生成相关报表。

查看原文

赞 3 收藏 0 评论 0

jovanywang 回答了问题 · 2018-01-10

TCP 主机A向主机B发送了三个TCP报文段,序号分别为30、100、180试问:(累积确认)。。。

  1. .第一个报文段携带了(69)字节的数据。

2.主机B收到第一个报文段后发回的确认号是(100),主机B收到第二个报文段后发回的确认号是(180)。

3.主机B收到第三个报文段后发回的确认号是280,试问A发送的第三个报文段中的数据有(99)字节。

4.主机B收到第三个报文段后发回的确认号是280,窗口字段为300,表明的含义是(希望A发序号为280的字节;B缓冲区只能接受300字节的大小)。

关注 4 回答 1

jovanywang 回答了问题 · 2018-01-10

解决TCP 四元组和五元组的问题

如果确定是tcp的话 就是 四元组可以唯一确定一个连接;

如果不能确定是tcp,而是传输层的话,就是五元组,外加一个协议。

关注 3 回答 2

jovanywang 回答了问题 · 2018-01-07

解决socket 编程中的粘包问题

首先,需要明确什么是tcp中的粘包问题(具体可wiki),我这里大致描述下:
tcp粘包就是指在tcp的网络编程(当然不止tcp,其他粘包也差不多意思)中,由于tcp是流式的,tcp提供给应用层的接口,无法获知发送端一次发了多少数据,也没办法获知发送端发了多少数据,就造成下一次数据头紧跟着上上一次数据尾,直接提供给应用层,应用层无法感知何处是发送端一次发送的边界。

下面说一下tcp粘包具体的原因:是发送端tcp层可能会对数据封装成多个tcp段,不仅如此,还会对应用层的多次数据组成一个包,比如应用层第一次写'A',第二次写'B',第三次写'C',在Tcp层很可能是发送一个tcp段,包含的数据是'ABC',所以,这样不管是接收端是否一次读一个tcp段,都无法分辨出哪里是发送端应用层边界,俗称"粘包"。

好,下面就简单说一下楼主(主要的错误也就1点):
图片描述

如我上面所说,接收端以如何的方式处理都不是粘包的根本原因,因此,接收端一次读一个tcp段也是会造成粘包现象,从而到处严重的错误。

那么如何解决粘包:
被采纳的答案的两条建议都是正确的,不过第一条容易让人引起误会,以为tcp可以一次读出定长的数据。
没什么好办法,就是应用层自己设置协议解决粘包问题,最典型的就是采用协议头部和数据的方式。注意的是,这里应该用状态机实现接收端的功能,因为你不能确定发送端发了完整的头部,你就一定能收到完整的头部。

最简单的办法就是设置8个字节的头部,表示数据长度,接着就是数据。
那么发送端先发送8个字节的一个数字,表示接下来的数据大小是多少,接着将数据全部发送过去。接收端一直接受数据,一直等到接受满了8个数据,取出来,计算出大小(假设为n),接着继续读取n个字节,就是完整的一个应用层的包了。

关注 5 回答 2

jovanywang 回答了问题 · 2018-01-06

tcp socket 发送文件,客户端如何判断接收到的是完整的文件?

  1. tcp socket判断数据是否完整的做法是制定合适的应用层协议解决(当然不排除特殊语言将这个协议内置在自己的socket api中),我不考虑这种特殊情况。

2.用到什么技术呢?有限状态机。那么有的同学可能不是很清楚有限状态机是个什么东西,不要紧,是个很简单东西。以这个问题举例,看完就知道了。

  1. 怎么做?很简单,我不是要发文件给对方吗,但是文件可能很大,几百G,也可能很小200B,对吧。不管怎么样,我们都没有办法假设认为发送端一次性往socket里面write能全部写进去,也没有办法认定接收端一次性能read出来。那我们就在发送的时候双方协商一个规则:我要给你发文件,最先会发4个字节(具体多少你自己定),这4个字节是的值就表示接下来这个文件的大小。那问题很好解决啦,发送端先判断即将发送的数据的大小,往socket中write一个4个字节的数,解决一直往socket中写文件,其他不用管,一直写,写完为止。那么接收端发现数据来了,先别管,读出4个字节,然后看这个数字是多大,说明接下来我要持续的读多少个字节,就能组成一个文件。完美解决。假设我连续发3个文件,没关系,接收端都是先读4个字节,假设读出来数据是10G,那么他接着读10G的数据出来,就是这个文件,接着在读4个字节,假设是200B,那么接着在读200B个字节数据出来,就是第二个文件的大小,以此类推。
  2. 上述的方式就是一个简单的状态机。

关注 3 回答 3

jovanywang 关注了标签 · 2018-01-06

关注 99

jovanywang 回答了问题 · 2018-01-06

数据结构关于图概念的理解

这只是一个概念:
平行边(定义):起点和终点相同的边互称为平行边。

关注 3 回答 2

认证与成就

  • 获得 17 次点赞
  • 获得 3 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 3 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2016-11-15
个人主页被 615 人浏览