@ruanxingzhi
2017-05-17T23:37:07.000000Z
字数 1168
阅读 1163
我是rxz,我又回来了。
我准备写一个OJ玩玩……撕烤一下各种细节。
整个OJ分成两块,web(服务鸡)和judger(评测鸡)。
用下面的这种方式把它们连接起来:
[Web] 收到评测请求
[Web] 找一只空闲的评测鸡,把任务发过去
[Judger] 收到任务
[Judger] 评测一番
[Judger] 返回评测结果
[Web] 收回评测结果
然后到底怎么实现“发任务”“返回评测结果”呢?本来准备用消息队列,但是感觉太麻烦了,于是用一个比较蛋疼的方式:HTTP API
(捂脸)
就是说,服务鸡收到评测任务后,访问http://Judger/judge.php
,把选手程序和题号用POST
的形式发过去;评测鸡测完之后,访问http://Web/back.php
,告诉服务鸡这份代码的评测结果。
好暴力啊……(捂脸)
Web
发给Judger
的数据应该是这样的:
{
id : 2333333, # 程序编号
problem : 1234, # 题号
code : "#include</dev/random>" # 选手程序
}
但是这里就有一个安全问题。如果一个选手,提交代码之后立刻访问http://Web/back.php
,然后假装自己是评测鸡,扬言他已经A题了,那服务鸡就会以为这人A题了。
这怎么办办啊?解决也很容易。我们给每个评测鸡分配一个口令,评测鸡返回评测结果的时候说一下口令,服务鸡就能知道评测鸡是不是假的了。当然,这个口令需要保密。
于是,Judger
发给Web
的数据应该是这样的:
{
id : 2333333, # 程序编号
name : "HongKong_Reporter", # 评测鸡名称
token : "dd9e36156587f472f876", # 认证
result : "AAAAAWWWWT", # 评测结果
time : "2333", # 用时(ms)
memory : "233333" # 空间(KB)
}
另外为了提高安全性,外网应该不能访问评测鸡。顺便也可以做一下服务鸡的验证,防止内网的黑恶势力冒充服务鸡给评测鸡发一大堆评测任务。
可能你会问了,为什么不让评测鸡连接上数据库,然后直接往数据库里面写东西?这样就不需要用HTTP API
来实现通讯了。
但是这个办法有一个不好:安全性。如果评测鸡不幸被人渗透,那么黑恶势力就可以随意修改数据库(至少是记载评测情况的那个数据库),这样就能篡改之前的评测记录。另外,数据库是不推荐允许localhost
以外的机器访问的。
HTTP API
实现的评测鸡还有一个好。在正常的OJ里,一个服务鸡可以对应多个评测鸡,但是一个评测鸡只能为一个服务鸡服务。然而现在,我们可以用一个评测鸡来对付很多个服务鸡,相当于评测资源共享了。
虽然这件事也能用直接改数据库的办法实现,但是比HTTP API
要麻烦一些。
服务鸡与评测鸡的通讯就谈到这里。下一篇我们谈谈OJ的文件结构吧。