数据类型

  • 可以通过查看帮助文档查阅所有支持的数据类型
  • 使用数据类型的原则是:够用就行,尽量使用取值范围小的,而不用大的,这样可以更多的节省存储空间
  • 常用数据类型如下:

    • 整数:int,bit
    • 小数:decimal
    • 字符串:varchar,char
    • 日期时间: date, time, datetime
    • 枚举类型(enum)
  • 特别说明的类型如下:

    • decimal表示浮点数,如decimal(5,2)表示共存5位数,小数占2位
    • char表示固定长度的字符串,如char(3),如果填充'ab'时会补一个空格为'ab '
    • varchar表示可变长度的字符串,如varchar(3),填充'ab'时就会存储'ab'
    • 字符串text表示存储大文本,当字符大于4000时推荐使用
    • 对于图片、音频、视频等文件,不存储在数据库中,而是上传到某个服务器上,然后在表中存储这个文件的保存路径
  • 更全的数据类型可以参考http://blog.csdn.net/anxpp/article/details/51284106

约束

  • 主键primary key:物理上存储的顺序
  • 自增auto_increment: 表示自动增长
  • 非空not null:此字段不允许填写空值
  • 惟一unique:此字段的值不允许重复
  • 默认default:当不填写此值时会使用默认值,如果填写时以填写为准
  • 外键foreign key:对关系字段进行约束,当为关系字段填写值时,会到关联的表中查询此值是否存在,如果存在则填写成功,如果不存在则填写失败并抛出异常
  • 说明:虽然外键约束可以保证数据的有效性,但是在进行数据的crud(增加、修改、删除、查询)时,都会降低数据库的性能,所以不推荐使用,那么数据的有效性怎么保证呢?答:可以在逻辑层进行控制

数据类型(常用)

类型字节大小有符号范围(Signed)无符号范围(Unsigned)
TINYINT1-128 ~ 1270 ~ 255
SMALLINT2-32768 ~ 327670 ~ 65535
MEDIUMINT3-8388608 ~ 83886070 ~ 16777215
INT/INTEGER4-2147483648 ~21474836470 ~ 4294967295
BIGINT8-9223372036854775808 ~ 92233720368547758070 ~ 18446744073709551615

字符串

类型字节大小示例
CHAR0-255类型:char(3) 输入'ab', 实际存储为'ab ', 输入'abcd' 实际存储为'abc'
VARCHAR0-255类型:varchar(3) 输'ab',实际存储为'ab', 输入'abcd',实际存储为'abc'
TEXT0-65535大文本

日期时间类型

类型字节大小示例
DATE4'2020-01-01'
TIME3'12:29:59'
DATETIME8'2020-01-01 12:29:59'
YEAR1'2017'
TIMESTAMP4'1970-01-01 00:00:01' UTC ~ '2038-01-01 00:00:01' UTC

数据库操作

  • 查看数据库列表
show databases;
  • 新增数据库
create database 数据库名字 charset=utf8;
  • 删除数据库
drop database 数据库名字;
  • 查看当前编辑的数据库
select databases();
  • 使用数据库
use 数据库名字;

数据表操作

  • 查看数据表列表
show tables;
  • 查看表结构
desc 表名;
  • 创建表
create table 名字(
    字段名 数据类型 约束条件,
    字段名 数据类型 约束条件,
    ...
    字段名 数据类型 约束条件
);
  • 修改表-添加字段
alter table 表名 add 字段名 数据类型 约束条件;
  • 修改表-修改字段-重命名版
alter table 表名 change 原名 新名 数据类型 约束条件;
  • 修改表-修改字段-不重命名版
alter table 表名 modify 列名 数据类型 约束条件;
  • 修改表-删除字段
alter table 表名 drop 字段名;
  • 删除表
drop table 表名;
  • 查看表的创建语句
show create table 表名;

因为给个人笔记本电脑升级,替换下来了一块2.5寸的1T机械硬盘,想着闲置也是闲置,不如用来搞一个nas玩玩,可以存放一些个人文件和电影大片,共享给家中的所有人,接下来就跟随我的脚步,一起来看看如何实现吧

1.前期准备

  • 树莓派(刷好官方系统,具体教程请见百度)
  • 闲置硬盘(可以是2.5寸,也可以是3.5寸,但前提是已经买好了硬盘壳子,能够支持USB连接)
  • 路由器

2.路由器MAC地址绑定

先说一下这一步是干嘛,众所周知,你树莓派连接家中的路由器会通过路由器的DHCP服务分配给你一个IP,但是这个IP租期到了的话会自行更换,为了一劳永逸,只要绑定MAC地址就可以实现永不更换IP,下面说一下操作步骤:

  • 进入后台页面
  • 从功能设置中找到DHCP服务,这里说一下基本路由器操作方式都是找到对应的DHCP服务选项!
  • 设置好自己的MAC地址和IP地址添加进去,如果说不知道自己的树莓派的MAC地址,也不用担心,下面会教你如何去寻找MAC地址
  • 进入终端管理,查看树莓派这个终端,你就能看到对应的MAC地址

3.配置samba文件共享服务

  • ssh登录
ssh pi@IP地址
  • 安装samba服务
sudo apt-get install samba -y
  • 编辑samba配置文件
sudo vim /etc/samba/smb.conf
  • 在文件末尾添加如下内容,如图所示
 [share]
    comment = Do not arbitrarily modify the database file
    path = /home/pi/share_files
    public = no
    writable = yes 

  • 重启samba服务
sudo service smbd restart
  • 在家目录下创建共享文件夹(以pi用户身份创建)
mkdir -p ~/share_files
  • 配置登录用户,因为samba服务需要有一个实体用户对应到虚拟用户中
sudo pdbedit -a -u pi 

4.配置硬盘自动挂载到共享目录

  • 连接你的硬盘到树莓派上,并查看你要挂在分区的UUID,这里我们要挂载的分区是/dev/sda2
sudo blkid

上图中圈出来的就是UUID,记下他

  • 编辑/etc/fstab,添加以下内容到最后一行,下面的UUID是你上面找到的UUID
PARTUUID=UUID /home/pi/share_files ntfs umask=000,uid=pi,gid=pi 0 0

5.解决树莓派不支持写入ntfs文件系统的问题

在做好以上工作之后,理论上你已经成功搭建了nas网盘,但是美中不足的是,这个网盘你连接上之后,是无法去进行写入文件的,因为树莓派的内核不支持在ntfs格式的文件系统的写入操作,我们需要打一个小补丁:

  • 安装nfts-3g模块
sudo apt-get install ntfs-3g -y
  • 更新内核模块
sudo modprobe fuse
  • 重启系统
sudo reboot

6.享用

  • Linux电脑下连接smb服务,以Ubuntu为例,这里我是已经点击了记住密码,所以不要求我去填写用户名及密码,第一次连接会提示你输入用户名密码,所以你需要填写的用户名是pi,密码是刚才你设置的密码

  • Android手机连接smb服务,从应用商场下载一个ES文件浏览器按照以下方式操作:

  • Windows连接smb服务,win+r呼出窗口,在窗口中输入\\IP地址\share,输入用户名和密码即可

Tips

QQ:770925351

WeChat:tc770925351

Email:770925351@qq.com

1.什么是Telegram

Telegram是款跨平台实时通信软件,客户端开源但服务器专有。服务器本身已加密外,可选额外用户对用户加密。支持传送所有文件类型,更支持语音通话。

2.Telegram的优点

作为一款优秀的即时通讯工具,它具有优秀的保密性,众所周知,x信现在各种收集用户隐私,而且用户也不能随心所欲的去聊自己想聊的东西,有很多的限制,但是在Telegram上却没有,正是因为它的隐蔽性、自由性和开放性,所以被一些国家封杀,只能扶墙出去才能使用这个软件,但是当时开发人员就已经想到了会有今天的封闭性,所以提前有了一款专门属于它的代理----MTProxy

3.什么是MTProxy

MTProxy是一款专门属于Telegram的代理服务,用户只需要在自己国外服务器上搭建这个服务,就可以不扶墙而去使用Telegram

  • 项目地址:https://github.com/TelegramMessenger/MTProxy

4.搭建MTProxy

  • 从github上拉取源码
git clone https://github.com/TelegramMessenger/MTProxy
  • 进入项目文件夹
cd MTProxy
  • 编译
make && cd objs/bin
  • 获取当前目录,并将这个目录记录下来
pwd
  • 获取与Telegram服务器的连接
curl -s https://core.telegram.org/getProxySecret -o proxy-secret
  • 获取配置文件
curl -s https://core.telegram.org/getProxyConfig -o proxy-multi.conf
  • 获取秘钥,记录下来
head -c 16 /dev/urandom | xxd -ps
  • 新建服务
vim /etc/systemd/system/MTProxy.service
  • 编辑服务文件,将以下内容保存到文件中,有以下注意事项:
  • 下面的目录是你上面获取的目录
  • 下面的端口号是你自己想要设置的端口,前提这个端口需要开放
  • 下面的秘钥是你上面获取的秘钥
[Unit]
Description=MTProxy
After=network.target

[Service]
Type=simple
WorkingDirectory=目录
ExecStart=目录/mtproto-proxy -u nobody -p 8888 -H 端口号 -S 秘钥 --aes-pwd proxy-secret proxy-multi.conf -M 1
Restart=on-failure

[Install]
WantedBy=multi-user.target

5.使用MTProxy

  • 启动服务
systemctl start MTProxy  # 启动服务
systemctl enable MTProxy # 将服务添加到开机启动项中
  • 使用,下面就是专门属于你自己的Telegram代理连接,赶快去试试吧

SERVER_NAME:你服务器的ip

PORT:你设置的端口

SECRET:你上面获取的秘钥

tg://proxy?server=SERVER_NAME&port=PORT&secret=SECRET

6.Tips

哪天心情好了可能会写一个自动脚本,今天就先这样,下面是我的联系方式,如果在使用过程中出现了什么问题,可以随时联系我

一键脚本已经写好,网址为:https://www.linuxstudy.cn/archives/54.html,请尽情享受吧。

7.我的微信公众号,欢迎各位的关注,有问题请在后台留言,或者加qq群764374820

我的微信公众号

Python 实现简易HTTP服务器

深入了解http协议的话,从底层看就是socket套接字通信利用一个规定的协议去发送和接收消息,再根据浏览器的解析将数据显示在前台页面,核心就是socket通信,所以http服务器的模拟就很容易了,原理就是这样,接下来直接上代码,代码需要你把自己的网站文件放在与http_server.py同一目录下的html目录中才能运行成功:

1.源码

http_server.py

''' 实现简单的http服务器,多进程版 '''
import socket
import re
import multiprocessing

def service_client(new_socket):
   # 接收浏览器发送过来的请求,也就是http请求
   request = new_socket.recv(1024).decode("utf-8")
   # 将request头部拆分,并采用正则将请求的页面解析出来
   request_lines = request.splitlines()
   # 匹配正则
   ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0]).group(1)
   # 如果是根目录直接解析到主页index.html
   if ret == "/":
       ret = "/index.html"   
   try:
       # 打开文件
       f = open("./html" + ret, "rb") 
   except:
       response = "HTTP/1.1 404 NOT FOUND"
       response += "\r\n"
       response += "----404 not found----"
       new_socket.send(response.encode("utf-8"))
   else:
       # 回复header
       response = "HTTP/1.1 200 OK\r\n"
       response += "\r\n"
       # 得到body内容
       html_content = f.read()
       f.close()
       # 发送header与body
       new_socket.send(response.encode("utf-8"))
       new_socket.send(html_content)
   # 关闭套接字
   new_socket.close()
def main():
   # 1.创建套接字
   tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

   # 设置选项,让服务器结束之后立即释放资源
   tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

   # 2.绑定
   tcp_server_socket.bind(("", 7709))

   # 3.变为监听套接字
   tcp_server_socket.listen(128)

   # 4.等待新客户端的链接
   while True:

       new_socket, client_addr = tcp_server_socket.accept()

       # 5.为这个客户端服务
       p = multiprocessing.Process(target=service_client, args=(new_socket,))
       p.start()
       new_socket.close()

if __name__ == "__main__":
   main()

2.运行效果

3.Tips

QQ:770925351

Wechat:tc770925351

E-mail:770925351@qq.com

在近日的Python学习中,再次学习到了TCP协议中比较精髓的部分,3次握手与4次挥手,记得以前网络原理老师给讲解时候的声容并茂,当时明白了,但是没有有效的记录,很快就忘记了,现在重新温习了一遍,好记性不如烂笔头,有效的记录是提高学习效率的好方法

一、3次握手

所谓3次握手,就是在client与server建立连接时候,client与server之间进行3次通信来建立有效的连接,如图所示:

第一次:客户端要连接到服务器,向服务器发送SYN数据包,并发送一个序号为X的数据

第二次:服务器接收到客户端发来的SYN数据包,并发送一个ACK报文,报文里的值为X+1,同时向客户端发送一个序号为Y的数据

第三次:客户端接收到服务器发来的SYN数据包,并发送一个ACK报文,报文的值为Y+1,然后与服务器建立连接

总结起来就是这么三句话:

今晚有空吗?吃个饭呗

有空,去哪吃

好的,我知道了,听我安排吧

二、4次挥手

所谓4次挥手,就是客户端与服务器断开连接时候,需要进行4次通信,来真正释放资源,断开连接,如图所示:

第一次:客户端要断开连接了,向服务器发送数据包,表示自己不会再发消息给服务器,跟3次握手相似,发送一个X数据和Z数据

第二次:服务器收到客户端发送的数据包,并发送一个X+1数据和Z数据,并确认客户端不会再发来数据

第三次:服务器向客户端发送一个数据包,表示自己不会再发数据给客户端,并发送一个Y数据和Z数据

第四次:客户端向服务器发送一个数据包,发送Y+1Z数据,确认服务器不会再发来消息

为什么这里会有四次?不像连接时候的3次,因为如果当你套接字close的时候才会有断开请求,所以说断开是主动的,不能跟发送数据是主动,所以返回数据和断开请求是分开的,在服务器发出断开请求之后,服务器会有一个超时时间来等待客户端发送返回回来的数据,只要客户端一发送过来服务器就立马释放资源,此时会有一个超时时间,如果等待不来客户端的第四次挥手,那么服务器就会再次重新发送第三次挥手的内容,而客户端在接收到第三次挥手的数据之后会进行第四次挥手,为确保第四次挥手能够正确发送到服务器并让服务器释放资源,客户端会有一个2分钟的TIME_WAIT,此时他会一直等待,当服务器释放资源结束等待,所以主动断开连接的一端会占用资源一会,这也是为什么你的tcp服务器在进行ctrl+C中止的时候不能立马再运行第二遍,因为主动断开连接的一端会有一个TIME_WAIT

4次挥手可以设置这么一个场景:

两个熟人在车站相遇,但是要分别去往不同的地方,此时两人要分别了:

A:我走了啊,我要去xxx

B:我知道了,你走吧

B:我也要走了,我要去yyy

A:我知道了,咱俩分头走吧

最近刚找了个国企的工作,虽然挺稳定吧,也很轻松,但是不是自己想干的,果断跑路辞职,毕业设计也已经确定了题目,开始搞了起来,各方面工作都开始启动,希望能够完成自己的目标吧,好像有点扯远了,继续说一下今天的小程序,这是我闲的没事情干写了个小东西,毕竟我是个懒人嘛,查快递每次得打开浏览器,输入网址,输入快递单号,真是麻烦,这个事情能不能用命令行实现呢?有了这个想法之后,利用一小会时间实现了这个小玩意,下面就不多赘述,开始说一下自己的思路:

1.整体思路

我们在查快递的时候,其实在浏览器输入地址然后再输入快递单号本质就是向服务器发出了一个GET请求,只要去进行正确的参数请求即可,然而Python的requests库就可以实现所有常见的http请求,分析返回来的数据即可,把有用的东西留下,并展示在前台界面,这就实现了我们的需求,比较知名的快递查询网站就是快递100啦,接下来开始搞起

2.F12万能大法

有了思路要开始考虑写程序的事情了,对于这种请求一般都是网站有专门api去进行调用数据库返回json信息,这时候就开始我们的F12万能大法,打开快递100首页,如图所示,主页挺漂亮的:

按下F12,并在单号输入框中输入单号,这时候发现页面一直在向一个api请求:

返回的json字符串正是单号所对应的快递公司,一部分信息取到:

api:http://www.kuaidi100.com/autonumber/autoComNum

参数有:

resultv2:1

text:快递单号

接下来搜索:

又出现了一个新的请求,看来这个就是获取到物流信息的api呀,得来全不费功夫

api:http://www.kuaidi100.com/query

参数有:

type:快递公司名称

postid:快递单号

phone:手机号后四位

3.程序源码

得到两个重要的api之后,我们就可以很快速的写出这个程序来,下面是程序源码:

快递查询.py

import requests

'''获取快递编号所对应的快递公司名称'''
def get_type(headers, express_code):
    type_list = []
    type_url = "http://www.kuaidi100.com/autonumber/autoComNum"
    params = {
        'resultv2' : 1 ,
        'text' : express_code
    }
    r = requests.get(type_url, headers=headers, params=params)
    result = r.json()
    type_dicts = result['auto']
    for type_dict in type_dicts :
        type_list.append(type_dict['comCode'])
    return type_list

'''向用户展示查询到的快递公司'''
def show_type(type_list, type_name):
    print("该运单号可能为以下快递:")
    for express_type in type_list:
        print(type_name[express_type])
    express_type = input("请输入您的快递种类(请输入快递种类的简拼,例如'顺丰'为'shunfeng'):")
    return express_type

'''主函数,查询快递信息'''
def main():
    type_name = {
        'yuantong' : '圆通' ,
        'shunfeng' : '顺丰' ,
        'yunda' : '韵达' ,
        'baishihuitong' : '百事汇通' ,
        'shentong' : '申通' ,
        'zhogntong' : '中通' ,
        'tiantian' : '天天' ,
        'jingdong' : '京东'
    }
    express_code = input("请输入要查询的快递单号:")
    phone_num = input("请输入手机的后四位数字:")
    msg_url = "http://www.kuaidi100.com/query"
    headers = {
        'User-Agent' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
    }
    type_list = get_type(headers, express_code)
    express_type = show_type(type_list,type_name)
    params = {
        'type' : express_type ,
        'postid' : express_code ,
        'phone' : phone_num
    }
    r = requests.get(msg_url, headers=headers, params=params)
    result = r.json()
    message = result['message']
    status_code = result['status']
    if status_code == '200':
        datas = result['data']
        print("您所查询的快递信息如下:")
        for data in datas:
            print(data['time'] + ":" + data['context'])
    else:
        print(message)

if __name__ == "__main__":
    while True:
        main()
        i = input("是否继续查询?(任意字符为继续,q为退出)")
        if i == "q":
            print("感谢使用,祝您生活愉快,再见!")
            break

4.运行效果

5.后记

其实快递100提供了很多api接口去为用户提供快递查询服务,本次是用了原生爬虫的思路,可能会有些啰嗦,但毕竟亲自实践得来的东西才是最爽的,这种分析思路是爬虫必须具备的,小程序只是具备查询type_name字典里面的快递类型,因为快递种类实在太多,懒得写了,小伙伴如果有兴趣的可以在type_name添加你想要查询的类型,在api返回的是简拼,为了让输出的更加好看一点,所以才有了type_name这个东西,如果你api返回的类型不在字典里,程序就会报错,想避免这个问题,就直接把程序中的print(type_name[express_type])修改为print(express_type),这样程序就不会报错,但是会显示快递公司的简拼,总之,东西技术含量不高,用来练练手就可以

6.Tips

QQ:770925351

Email:770925351@qq.com

Python之网络编程

每一门编程语言最经典的就是实现网络Socket编程,Python肯定也有这方面的库和函数,下面就来谈谈Python的Socket编程

ps:这篇文章是博主在火车上码的,有些水,实在是没事干,大佬勿喷(手动滑稽)

1.本次模块

socket

2.UDP通信

server.py

#!/usr/bin/env python
# coding=utf-8

import socket
# 创建UDP套接字
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 定义ip地址及端口
local_addr = ("",7709)
# 绑定地址
s.bind(local_addr)
# while循环实现一直接收信息
while True :
    # 接收消息,返回的是消息以及ip地址端口
    recv_data = s.recvfrom(1024)
    # 对消息进行解码
    msg = recv_data[0].decode("utf-8")
    # 判断,如果退出,服务器退出
    if msg == "exit":
        break;
    print(msg)
# 关闭套接字
s.close()

client.py

#!/usr/bin/env python
# coding=utf-8
import socket
# 创建套接字
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 初始化服务器端口地址
send_addr = ("",7709)
# while循环
while True:
    # 中断发送消息
    send_data = input("请输入要发送的消息:")
    # 发送到服务器
    s.sendto(send_data.encode("utf-8"),send_addr)
    # 判断是否退出
    if send_data == "exit":
        break;
# 关闭套接字        
s.close()

3.TCP

server.py

#!/usr/bin/env python
# coding=utf-8

import socket

# 设置服务器的绑定地址及端口
server_addr = ("",7709)

# 创建tcp套接字
server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# 绑定本地地址及端口
server_socket.bind(server_addr)

# 将tcp套接字转换为被动链接状态
server_socket.listen(128)

while True :
# while循环实现多个客户端进行连接
    print("服务器等待连接~~~~")
    # 每当一个客户端进行连接的时候,创建一个新的套接字,并获得客户端ip地址
    client_socket,client_addr = server_socket.accept()
    print("ip:%s的客户端已经连接" % (str(client_addr)))
    # 当一个客户端进行连接时,一直循环接收这个客户端的信息
    while True :
        recv_data = client_socket.recv(1024)
        print("%s:%s" %(str(client_addr),recv_data.decode("utf-8")))
        if recv_data:
            pass
            if recv_data.decode("utf-8") == "exit":
                exit()
        else :
            break;
    print("ip:%s的客户端已经断开" % (str(client_addr)))
    client_socket.close()

client.py

#!/usr/bin/env python
# coding=utf-8
import socket
# 创建套接字 tcp套接字
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 初始化ip地址及端口
server_addr = ("",7709)
# 连接套接字
s.connect(server_addr)
# 死循环,当信息收到exit时候退出循环,断开连接
while True:
    
    send_data = input("请输入要发送的数据:")

    s.send(send_data.encode("utf-8"))

    if send_data == "exit":
        break;
# 关闭套接字    
s.close()

4.Tips

QQ:770925351

Email:770925351@qq.com

WeChat:tc770925351