onlineJudge

2025-12-07 0 604

Online Judge


0. 简介

  • 首先是一定要感谢HUST OJ的大大们的,阅读源代码的过程中经验值飞增。
  • 这是一个使用JSP实现的简单的OJ,对数据库的操作均通过调用存储过程和激发触发器来实现。(所以最后写出来的存储过程好多啊。。。。)
  • 数据库的信息,例如地址啊用户名啊密码啊没有写在Java类里,而是写了一个叫做databaseInfo.xml的文件(在web/WEB-INF路径下),然后用一个监听类来获取这个文件的绝对路径地址,在ConnectionDao这个类里读取出相应的信息,这样移植起来就方便啦,不给源码只给编译后的class文件的话也可以修改数据库。
  • 判题的隔离问题使用Docker来实现,下载了一个ubuntu镜像,然后自己在镜像中安装gcc, g++, java, 并新建一个弱权限的用户。把修改后的镜像保存起来,在判题时进入docker使用弱权限用户运行程序。
  • JSP只负责前端和处理用户提交的信息。用户提交代码后,JSP将信息写入数据库,提交状态设置成queueing,之后就不需要管了,全权交给Linux端去弄。
  • Linux端有两个程序,一个是轮询程序(polling.cpp),另一个是判题程序(judge.cpp),两个程序的参数都是通过命令行传参的,因此我又另外写了两个shell脚本(startup.sh和judge.sh)去执行程序。
  • Linux端C++与数据库的连接是使用mysql-connector-c++实现的。

1. 目前实现的功能

  • 登录、注册、修改个人信息; (这不是废话吗)
  • 通过竞赛的标题搜索相关的竞赛;
  • 可以根据用户名、代码提交的结果、编程语言来查看提交状态;
  • 管理员增删改题目、样例,添加竞赛;
  • 使用JQuery富文本编辑器编辑题目信息;
  • 用户可以提交C、C++、JAVA程序;
  • 限制每个账号30秒内只能提交一次;
  • 后台判题使用Docker,能判断AC、WA,能处理编译超时,运行超时,内存超限,输出超限,运行错误这几种情况。
  • 竞赛/作业加密功能,且用户登录正确之后就不需要再输入密码;
  • 竞赛模式和练习模式,竞赛模式有时间限制,时间截止就无法提交,而练习模式无限制;
  • 用户提交代码可以选择是否公开自己的代码,其他用户可以在竞赛结束后查看别人公开的代码;
  • 增加总排行榜,显示AC数、AC率;
  • 分页显示信息;
  • 测试数据文本文件上传;
  • 判题按队列顺序进行,全权由linux处理。
  • 通过使用setrlimit和alarm限制时间、内存、输出文件大小、可产生的进程数等,ptrace监听控制,实现防止#include \”/dev/random\”头文件造成的编译无法停止,死循环程序攻击,疯狂输出,fork炸弹,系统调用等攻击手段,同时,使用Docker进行隔离,容器炸了也不关我主机的事,判题结束后容器会被删除,下次判题又是新的容器。
  • 通过ptrace获取子进程的syscallId,并与允许的系统调用id进行比对,若不在许可列表中,则返回RE。自己手动跑了几个程序打表打出好多常规程序会产生的系统调用Id,但是怕漏了几个导致误判,就借鉴了HUST OJ源码中的过滤列表。(再次感谢大佬们开源)

2. 主要判题流程

  • 使用 nohup ./startup.sh $ 命令可以让进程在后台运行,退出终端后程序也不会终止。这个脚本会执行polling程序,并将相关的参数以命令行的形式传进程序中。polling程序是一个死循环的轮询程序。程序获取参数后,会连接数据库,然后调用存储过程将数据库中所有状态为queueing的提交按提交时间排序,先提交的排前面,全部放进队列里,然后断开数据库连接。如果队列不为空,就将数据逐个拿出来,把代码写入到文件中后,fork()一个子进程去启动judge.sh脚本,父进程就用waitpid()等待子进程结束。一直到队列为空。之后就sleep一秒中,然后继续刚才的操作,查询数据库的信息并判题。
  • judge.sh文件做两件事,一件是把编译后的judge程序拷贝到所要隔离的目录下(当初写这个是怕用户程序把目录下所有文件都删了,导致后续无法判题,现在想想,似乎删不了正在执行的程序,不过这样做了之后,我在修改judge文件之后,就不需要再手动拷过去了2333),另一件事是运行Docker,并在Docker中运行judge程序。
  • judge程序是判题程序。首先是通过传递的参数编译用户的源代码,如果编译出错,则向数据库写入系统错误或编译错误及错误信息;否则,开始判题。判题时,通过链接数据库获取题目限制的时间和内存,并读取所有的输入数据、输出数据。对于每组数据,先将输入数据写入到当前工作目录下的文件中,然后fork()一个子进程去运行代码,并用freopen重定向输入数据为刚才保存的文件、输出为文本文件,stderr也重定向为文本文件。父进程用ptrace监控该子进程,若达到超时、超内存、状态异常等情况,则改变判题结果为对应的状态,并结束子进程。若子进程正常结束,则比对一下用户输出与该组输出数据。判题直到数据全跑完,或者判题结果不再是AC,就可以结束了。最后就是更新数据库结果了。(PS:Docker默认不能使用ptrace,这个bug调了好久,最后才发现是Docker的问题。。。在启动Docker之前,加入启动选项 –cap-add=SYS_PTRACE就行了。)
  • 运行时间的获取可以直接有usage得到,而内存大小就搞不定了。通过研究HUST OJ的源代码,发现进程在运行的时候,会产生 /proc/pid/status这个文件(pid就是该进程的pid),里面记录了挺多内存信息的,且单位是KB,需要自己转一下,那么问题就变成文件读取了。(这是C和C++的,JAVA的需要到另一个地方看,应该是因为JVM的关系。)

3. 计划拓展功能

  • 批量生成竞赛用户账号,并加入到竞赛中;
  • 通过邮箱找回密码;
  • 数据下载,包括竞赛排行榜、总排行榜、题目信息、竞赛信息等;
  • 除管理员外,其他用户查看别人的代码,均将代码生成为图片;

下载源码

通过命令行克隆项目:

git clone https://github.com/mufeng964497595/onlineJudge.git

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 开发教程 onlineJudge https://www.zuozi.net/31407.html

BiliHP APP
上一篇: BiliHP APP
learn classic asp
下一篇: learn classic asp
常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务