qcr
1 License
2 简介
3 构建系统
4 安装使用
5 工作流程
6 协议
7 数据包生成和处理
8 抽象和扩展
8.1 Logging
filesystem-logger
network-logger
eval-logger
filesystem-error-log-receiver
eval-error-log-receiver
eval-info-log-receiver
network-error-log-receiver
network-debug-log-receiver
log-receivers
8.2 数据包
all-confirm
download-location
allow-eval
allow-unsafe-eval
processor<%>
make
parse
message-processor%
link-processor%
file-processor%
directory-processor%
command-processor%
unsafe-command-processor%
local-command-processor%
<type>?
registry
9 兼容性问题
10 更新
11 项目状态
8.6

qcr

haozhang

A small chat room on tcp protocol.

1 License

This program is released under LGPL-3.0-only.

2 简介

qcr是一个实验性的点对点网络通信程序,可以实现基本的聊天以及文件、目录和链接的共享,如果有需要也可实现某些自动化的功能。

3 构建系统

过去使用make和Makefile进行构建,由于作者能力有限始终无法实现对更多平台和系统的支持,目前已弃用。

从v0.1.3开始使用zuo进行构建(dependencies见"info.rkt")。

"main.zuo"提供以下target:clean、install、uninstall、test、setup、exe、dist。要执行特定的任务,请使用zuo . [target name]

前五个target为PHONY target,target name即为其本身的名称;exe的target name为"main"(windows系统需加扩展名".exe");dist的target name格式为"qcr-[system]-[arch].zip"

功能上,

执行某一特定任务时,zuo总是首先读取"main.zuo",而这一文件导入了"check.zuo",后者会对运行环境进行一些检查,以确定哪些target可用。使用当前不支持的target会引起一个错误。

4 安装使用

[1]已经安装好Racket。

  1. raco pkg install qcr

  2. racket -e "(require (submod qcr main))" -- [命令行参数]

[2]使用编译好的可分发包。

解压并进入"main"/"main.exe"可执行程序所在目录并执行命令即可。

使用--help查看使用说明。

5 工作流程

6 协议

传输层使用TCP协议,不赘述。

应用层协议基于Racket port构建。

7 数据包生成和处理

因此,

8 抽象和扩展

8.1 Logging

 (require qcr/logging) package: qcr
提供了一些logger和log receiver。

logger

filesystem-logger : logger?

记录文件系统相关的信息。

logger

network-logger : logger?

记录网络相关的信息。

logger

eval-logger : logger?

记录evaluator相关信息。

log-receiver

filesystem-error-log-receiver : log-receiver?

接收文件系统级别为'error的信息。

log-receiver

eval-error-log-receiver : log-receiver?

接收evaluator级别为'error的信息。

log-receiver

eval-info-log-receiver : log-receiver?

接收evaluator级别为'info的信息。

log-receiver

network-error-log-receiver : log-receiver?

接收网络级别为'error的信息。

log-receiver

network-debug-log-receiver : log-receiver?

接收网络级别为'debug的信息。

dispatcher

log-receivers

 : (hash/c (or/c 'none 'fatal 'error 'warning 'info 'debug) (listof log-receiver?) #:immutable #t)
按照level对log receiver进行分类。处理命令行参数时使用。

8.2 数据包

 (require (submod qcr extension))
定义了数据包的生成和解析方式。

parameter

(all-confirm)  any/c

(all-confirm v)  void?
  v : any/c
 = #f
若此参数值为true则文件下载无需确认。

parameter

(download-location)  path-element?

(download-location v)  void?
  v : path-element?
 = "file"
指定文件下载位置为当前(工作)目录下某个文件夹。

parameter

(allow-eval)  any/c

(allow-eval v)  void?
  v : any/c
 = #f
若此参数值为true则在沙盒中执行对方发送的所有指令而无需确认。

parameter

(allow-unsafe-eval)  any/c

(allow-unsafe-eval v)  void?
  v : any/c
 = #f
类似于allow-eval,但决定的是unsafe command能否执行。

请注意执行对方发送的指令时可以对以上这些参数进行修改,如果不是绝对信任请不要授予不必要的权限。

所有类型数据包都由此接口的一个实现(即一个processor)进行生成和解析。 这些processor都接受一个input port作为初始化参数,这个port可能包含有命令行输入内容或TCP port中读取和解密的信息(均不含有类型信息),分别对应于make和parse两种public方法。

method

(send a-processor make)  input-port?

method

(send a-processor parse)  any/c

make方法必须返回一个input port供后续加密和传输使用,而parse方法可以返回任意值。此接口就是针对这两个方法的行为进行检查。

如需自定义数据包类型,无需将processor作为此接口的一个实现,只须实现为一个符合以上描述的类即可,如需边界检查请自行添加。

以下为extension模块原生支持的processor。

class

message-processor% : class?

  superclass: object%

  extends: processor<%>

class

link-processor% : class?

  superclass: message-processor%

  extends: processor<%>

class

file-processor% : class?

  superclass: object%

  extends: processor<%>

class

directory-processor% : class?

  superclass: file-processor%

  extends: processor<%>

class

command-processor% : class?

  superclass: object%

  extends: processor<%>

class

unsafe-command-processor% : class?

  superclass: command-processor%

  extends: processor<%>

parser

(<type>? port)  symbol?

  port : input-port?
接受一个TCP port或string port,根据其数据包类型信息产生一个symbol用于后续调度。

如需自定义此函数(如使用++import标记时)请将数据包类型信息从此port中消耗掉。 此外,在通用的预处理过程中'message总是作为保留类型而被特殊对待,因为其数据包中无类型信息。

dispatcher

registry

 : (hash/c symbol? (implementation?/c processor<%>) #:immutable #t)
以类型解析生成的symbol为key获取对应的processor

在自定义数据包时,一般首先实现processor,然后通过<type>?规定(current-input-port)和TCP port中的类型信息,并将代表类型信息的symbol和processor打包为registry哈希表, 最后通过++import从模块中导入自定义的<type>?registry(一定记得在这两者中预留'message和对应的processor)。

9 兼容性问题

10 更新

后续更新

v0.1.8

2022.9.3

v0.1.7

2022.9.1

v0.1.6

2022.8.29

v0.1.5

2022.8.25

v0.1.4

2022.8.18

11 项目状态

此项目是作者用于自学网络编程和Racket语言的实验性项目,这个目的已经基本达到了,因此不会再添加新的功能,但仍会继续维护。

有任何bug和好的想法欢迎提issue至github