P2P系统设计项目 - 服务器后端。使用JavaScript + MySQL搭建后端接口,提供数据交互功能。
References
【万物4分钟】磁力下载是什么原理?跟用种子下载的区别大不大?
种子文件 .torrent
BEncoding 编码格式
BEncoding 是一种用于组织、描述数据的简洁编码格式,它支持 4 种数据类型 / 元素:
- 字节串(Byte String)
- 整数(Integer)
- 列表(List, 线性表)
- 字典(Dictionary)
字节串
格式为 长度:内容
。
例如:
4:abcd
:”abcd”0:
:空串
BE字节串,不是字符串,因此在字典中 key 的比较是二进制比较而不是字符串比较。
整数
格式为 i + 整数 + e
。
例如:
i1234e
:1234i-1e
:-1i0e
:0
列表
格式为 l + 元素:元素:...:元素 + e
。
例如:
l4:spam4:eggse
:[ “spam”, “eggs” ]li123e5:helloi111ee
:[ 123, “hello”, 111 ]le
:空列表
字典
格式为 d + 字节串:元素:...:字节串:元素 + e
。
例如:
d3:cow3:moo4:spam4:eggse
:{ “cow” => “moo”, “spam” => “eggs” }d4:name5:Angus3:agei23ee
:{ “name” => “Angus”, “age” => 23 }d4:spaml1:a1:bee
:{ “spam” => [ “a”, “b” ] }de
:空列表
Torrent文件结构
Torrent整体是一个Bencoding编码的字典,其中有以下的属性名。
键名称 | 数据类型 | 可选项 | 键值含义 |
---|---|---|---|
announce | string | required | Tracker的Url |
info | dictionary | required | 该条映射到一个字典,该字典的键将取决于共享的一个或多个文件 |
announce-list | array[] | optional | 备用Tracker的Url,以列表形式存在 |
comment | string | optional | 备注 |
created by | string | optional | 创建人或创建程序的信息 |
Info字段
在总体结构中有个info,其为字典格式。
单文件、多文件的有不同的info属性。
单文件Info结构
键名称 | 数据类型 | 可选项 | 键值含义 |
---|---|---|---|
name | string | required | 建议保存到的文件名称 |
piceces | byte[] | required | 每个文件块的SHA-1的集成Hash。 |
piece length | long | required | 每个文件块的字节数 |
多文件Info结构
键名称 | 数据类型 | 可选项 | 键值含义 |
---|---|---|---|
name | string | required | 建议保存到的目录名称 |
piceces | byte[] | required | 每个文件块的SHA-1的集成Hash。 |
piece length | long | required | 每个文件块的字节数 |
files | array[] | required | 文件列表,列表存储的内容是字典结构 |
files字典结构:
键名称 | 数据类型 | 可选项 | 键值含义 |
---|---|---|---|
path | array[] | required | 一个对应子目录名的字符串列表,最后一项是实际的文件名称 |
length | long | required | 文件的大小(以字节为单位) |
Torrent解析
https://github.com/ndroi/pytorrent 不太好用
parse-torrent 这个是JS版本的
torrent_parser python版本
既可以解析磁力链接,也可以解析种子文件。
1 | const parseTorrent = require('parse-torrent') |
开源torrent
libtorrent 开源P2P
1 | sudo apt-get install python3-libtorrent |
运行示例:https://github.com/arvidn/libtorrent/blob/libtorrent-1_0_7/bindings/python/client.py
1 | python3 client.py demo.torrent |
demo.torrent
为一个测试种子文件。
WebTorrent 开源P2P
WebTorrent is a streaming torrent client for Node.js and the web. WebTorrent provides the same API in both environments.
The WebTorrent protocol works just like BitTorrent protocol, except it uses WebRTC instead of TCP/uTP as the transport protocol.
在Webtorrent的API中支持直接访问种子中的各个字段:
JSON文件 .json
JSON(JavaScript Object Notation)是一个数据交换协议规范。它的设计简约,从而在Web开发中得到大量的应用。JSON文件后缀为.json
。不同的语言中存在不同的对JSON文件的解析器,如JavaScript中的eval()
函数。
在不同的系统不同的语言间交换数据时,我们一般倾向于使用无关于平台及语言的数据交换语言。此类语言主要包括XML,JSON,YAML,Protobuf等,常用于接口调用,配置文件,数据存储等场景。
元素
JSON允许以下基本元素 / 值(value):
- 字符串(string)
- 数值(number)
- 布尔值(true、false)
- 空值(null)
以及嵌套元素:
- 对象(object)
- 数组(array)
一个JSON文件就是一个元素(具有任意的复杂度)。
在JavaScript中可以直接创建JSON格式的变量。
1 | var employees = [ |
可以像这样访问 JavaScript 对象数组中的第一项:
1 | employees[0].lastName; |
返回的内容是:
1 | Gates |
可以像这样修改数据:
1 | employees[0].lastName = "Jobs"; |
对象 {}
一个JSON对象就是一个字典,即,“键-值对”(key: value
)。
1 | { |
数组 []
JSON 数组在方括号中书写。
1 | { |
NPM 前端套件管理器
NPM(Node Package Manager),前端套件管理工具。除此之外还有类似的Yarn。
Node.js:一种javascript的运行环境,能够使得javascript脱离浏览器运行。它是一种提供给后端服务器的技术。
Package.json
- name - 包名。
- version - 包的版本号。
- description - 包的描述。
- homepage - 包的官网 url 。
- author - 包的作者姓名。
- contributors - 包的其他贡献者姓名。
- scripts - 指定了运行脚本命令的npm命令行缩写。比如start指定了运行
npm run start
时,所要执行的命令。 - dependencies - 依赖包列表。如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下。
- repository - 包代码存放的地方的类型,可以是 git 或 svn,git 可在 Github 上。
- main - main 字段指定了程序的主入口文件,require(‘moduleName’) 就会加载这个文件。这个字段的默认值是模块根目录下面的 index.js。
- keywords - 关键字
npm init
NPM通过初始化项目来填写基本信息,并创建Package.json
文件。
npm install
npm install
检查当前位置下的package.json
,并根据该文件计算缺少的套件,自动更新相关的依赖。并且生成node_modules
文件夹用于保存下载的依赖包。
安装指定模块:
1 | npm install <Module Name> |
安装并记录到Package.json
:
1 | npm install express --save # 将该模块写入dependencies属性 |
全局安装:
1 | npm install express -g # 全局安装 |
卸载:
1 | npm uninstall <Module Name> |
查看依赖树:
1 | npm ls |
版本检查:
1 | npm -v |
升级:
1 | sudo npm install npm -g |
npm run <scripts>
运行Package.json
中”scripts”属性所设置的脚本。比如:
1 | npm run start |
Qingqing Share 前端
安装
1 | git clone https://github.com/zouyansong/qingqingshare |
试运行
1 | sudo apt install npm |
将
PATH=$(echo "$PATH" | sed -e 's/:\/mnt.*//g') # strip out problematic Windows %PATH%
添加到~/.bashrc
.
Tracker服务器
资源服务器
数据库服务器
MySQL安装
检查本地环境:
1 | rpm -qa | grep mysql |
获取Mysql:
1 | sudo wget http://dev.mysql.com/get/mysql-apt-config_0.8.1-1_all.deb |
安装软件包:(dpkg « Linux命令大全)
1 | sudo dpkg -i mysql-apt-config_0.8.1-1_all.deb |
安装mysql-server,选择5.7的稳定版本
更新软件源:
1 | sudo apt update |
安装mysql-server:
1 | sudo apt install mysql-server |
设置数据库root用户的密码
MySQL服务管理
1 | # 启动mysql服务 |
mysql默认监听3306端口
MySQL登录
以root用户进行登录:
1 | mysql -u root -p |
然后输入密码
查看用户列表:
1 | USE mysql; |
https://stackoverflow.com/questions/39281594/error-1698-28000-access-denied-for-user-rootlocalhost 初次安装后无法登录的处理
管理员强制登陆:
1 | sudo mysql -u root # I had to use "sudo" since is new installation |
https://stackoverflow.com/questions/50093144/mysql-8-0-client-does-not-support-authentication-protocol-requested-by-server JavaSccript mysql连接数据库失败的处理
用户生成
MySQL 管理 新版MySQL不再支持直接向user表中添加用户。需要使用
CREATE USER
声明。
1 | CREATE USER username@hostname IDENTIFIED BY password; |
例如:下面这个用户只允许从localhost
主机并使用密码为guest233
连接到MySQL数据库服务器。
1 | CREATE USER guest@localhost IDENTIFIED BY 'guest233'; |
@localhost
相当于访问地址的约束。MySQL user DB does not have password columns - Installing MySQL on OSX
mysql> describe user;
权限管理
1 | GRANT privilege,[privilege],.. ON privilege_level |
赋予auditor
在某个数据库上的所有权限:
1 | GRANT ALL ON somedb.* TO auditor@localhost; |
创建数据库和表单
1 | CREATE DATABASE qqshare; |
创建qqshare_info
数据表:
1 | CREATE TABLE IF NOT EXISTS qqshare_info( |
创建user_info
数据表:
1 | CREATE TABLE IF NOT EXISTS user_info( |
删除表
1 | DROP TABLE qqshare_info; |
查看数据表
1 | show tables; |
1 | +-------------------+ |
插入数据
1 | INSERT INTO qqshare_info ( field1, field2,...fieldN ) |
清洗测试:
1 | use qqshare; |
查看数据项
1 | SELECT * FROM qqshare_info; |
搜索初探
查询
用SQL查询代替搜索。
1 | SELECT * |
1 | SELECT filename, course, teacher |
Local种子匹配
1 | import socket |
Node Express 后端
Node项目配置
检查Node版本:
1 | node -v |
测试JS程序server.js
:
1 | var http = require('http'); |
运行测试程序server.js
:
1 | node server.js |
访问http://localhost:8880/
即可得到结果。页面返回'Hello World\n'
。
在测试完成之后按Ctrl C
退出程序,Ctrl Z
只是退出界面,会导致程序继续运行,端口号被占用。
Express风格
1 | //express_demo.js 文件 |
访问http://localhost:8081/
得到结果。页面返回'Hello World'
。
服务器设计
1 | // 测试查询链接: |
服务器持续运行
在执行的命令之前增加nohup,在命令后增加&。然后点任意键退回到shell,再exit,node.js程序仍然会在后台运行。
如;nohup npm start &
nohup命令
不挂断地运行命令。
1 | nohup Command [ Arg … ] [ & ] |
nohup命令将当前指令的所有输出都输出到了当前文件夹下的nohup.out文件。加不加&并不会影响这个命令。只是让程序前台或者后台运行而已。
使用 jobs 查看任务。
使用 fg %n 关闭。
screen命令
1 | screen |
Screen将创建一个执行shell的全屏窗口。你可以执行任意shell程序,就像在ssh窗口中那样。在该窗口中键入exit退出该窗口,如果这是该screen会话的唯一窗口,该screen会话退出,否则screen自动切换到前一个窗口。
1 | screen vi test.c |
Screen创建一个执行vi test.c的单窗口会话,退出vi将退出该窗口/会话。
byobu命令
Unbuntu图形界面可以使用,更加集成化,且可以使用快捷键。
1 | sudo apt install byobu |
【pm2】
安装
1 | sudo npm install -y pm2 -g |
运行
如有必要,修改Package.json
中的start
接口:
1 | "start": "node server.js" |
通过pm2运行项目:
1 | sudo pm2 start server.js |
不要忘记添加项目启动脚本
server.js
。这个可以用~
查看
查看当前运行的项目:
1 | sudo pm2 ls # 或: sudo pm2 list |
日志
pm2生成的日志文件的默认路径在$ HOME /.pm2/logs /下面。
1 | cd ~/.pm2/logs/ |
查看历史日志:
1 | sudo pm2 logs --lines 200 # 查看历史日志 |
查看实时日志:
1 | sudo pm2 logs # 实时显示日志 |
其他日志操作:
1 | sudo pm2 logs --raw # 显示流中的所有进程日志 |
仪表盘
仪表盘可以显示实时监控的动态数据,退出Ctrl+C
1 | sudo pm2 monit # 查看仪表盘 |
停止
停止当前运行的项目:
1 | sudo pm2 stop server # 停止项目名为server的应用程序 |
重启
1 | sudo pm2 restart all # 重启pm2管理的所有应用程序 |
删除
1 | sudo pm2 delete server # 删除项目名为sever的应用程序的进程 |
自启动
服务器开机自启动。
1 | sudo pm2 startup |