您当前的位置: 首页 > 
  • 5浏览

    0关注

    322博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

毕设项目:基于BS模型的在线OJ系统

森明帮大于黑虎帮 发布时间:2022-03-25 17:31:38 ,浏览量:5

在这里插入图片描述

系列文章目录

文章目录
  • 系列文章目录
  • 前言
  • 一、在线OJ系统描述
  • 二、在线编译模块
      • 1.搭建一个HTTP服务器完成在线编译
      • 2.收到HTTP请求,进行数据格式转化(HTTP中body的内容转换为JSON格式的字符串)
      • 3.compile_server.cpp浏览器提交JSON数据请求服务器,服务器调用在线编译模块编译,把结果返回给浏览器
      • 4.util.hpp工具类
        • 1.TimeUtil类时间戳获取工具TimeUtil标识文件的不同
        • 2.打印日志的工具
        • 3.文件类FileUtil把文件所有内容读取出来,放到content字符串中
        • 4.URL body解析模块
        • 5.查找用户代码中是否有危害服务器的语句
      • 5.compile.hpp在线编译类
        • 1.源代码的文件
        • 2.编译错误文件
        • 3.可执行程序文件
        • 4.标准输入文件
        • 5.标准输出文件
        • 6.标准错误文件
        • 7.CompileAndRun函数
        • 8.WriteTmpFile函数
        • 9.Compile函数
        • 10.Run函数
      • 6.post提交到所有问题界面
      • 7.在线编译模块小结
  • 三、题目管理模块
      • 1.oj_data存放题目的文件夹
        • 1.oj_config.cfg每一行都代表一个题目
        • 2.header.cpp代码框架
        • 3.tail.cpp代码测试用例
        • 4.desc.txt题目详细描述
      • 2.MVC中的M负责存储数据 oj_model.hpp这个oj_model模块做的事情,就是把刚才文件中存储的题目信息加载起来,供服务器使用
        • 1.描述题目的类question
        • 2.load函数表示把文件中的数据加载到内存中, 加到哈希表中
        • 3.GetAllQuestion获取所有题目
        • 4.GetQuestion获取某个具体的题目
      • 3.MVC中的C controller: 核心业务逻辑 oj_server.cpp作为服务器的核心逻辑,需要创建好对应的服务器框架代码,在这个框架中来组织逻辑
        • 1.all_questions核心业务逻辑
        • 2.question核心业务逻辑
        • 3.compile核心业务逻辑
      • 4.oj_server.hpp对于oj_server.cpp的实现部分controller 作为服务器的核心逻辑,需要创建好对应的服务器框架代码,在这个框架中来组织逻辑
        • 1.server.Get("/all_questions")
        • 2.server.Get(R"(/question/(\d+))"
        • 3.server.Post(R"(/compile/(\d+))"
      • 5.MVC中的v V => view : 负责显示界面 oj_view.hpp根据数据,生成html这个动作,通常叫做网页渲染(render)
        • 1.RenderAllQuestion渲染所有问题界面
        • 2.RenderQuestion渲染单个问题界面
        • 3.RenderCompileResult渲染结果界面
  • 三、前端结果界面
      • 1.all_question.html
      • 2.question.html
      • 3.result.html
  • 总结

前言

在这里插入图片描述

一、在线OJ系统描述

实现一个在线OJ系统类似于力扣或者牛客网的核心部分刷题代码练习功能,提供了用户一个可以在线刷题编写代码并且能够进行编译运行的环境,题目通过序号排序,题目也有难度等级的划分,测试用例等等。在编写代码的同时提供了语法纠错、代码高亮、自动补全等基本功能。 在这里插入图片描述

用户可以通过域名加上端口号访问服务器,系统内置了多道编程题,用户点击对应题目就可以进行练习,并且题目内含有大量测试样例。服务器端会根据用户编写代码会进行用例的测试,检测用户代码是否符合题意,并且可以将编译成功结果或者编译出错的原因返回给浏览器端。

二、在线编译模块

在这里插入图片描述 在这里插入图片描述 在现编译模块的实现:此模块的核心完成"在线",用户把写好的代码通过网页提交到服务器上,服务器调用g++完成编译过程,并且调用刚生成的可执行程序,验证程序结果,返回给用户提交的浏览器上。

1.搭建一个HTTP服务器完成在线编译

搭建一个HTTP服务器来完成在线编译的核心功能。

此处开源的Httplib源代码:cpp-httplib 或者直接git clone: git clone https://github.com/yhirose/cpp-httplib

在这里插入图片描述

A C++11 single-file header-only cross platform HTTP/HTTPS library.

It's extremely easy to setup. Just include the httplib.h file in your code!

NOTE: This is a multi-threaded 'blocking' HTTP library. If you are looking for a 'non-blocking' library, this is not the one that you want.

翻译:一个C++11单文件头文件跨平台HTTP/HTTPS库。

它非常容易安装。只需在代码中包含httplib.h文件即可!

注意:这是一个多线程的“阻塞”HTTP库。如果你正在寻找一个“非阻塞”库,这不是你想要的。

在这里插入图片描述 快速上手一个开源项目小技巧: 在这里插入图片描述

2.收到HTTP请求,进行数据格式转化(HTTP中body的内容转换为JSON格式的字符串) 3.compile_server.cpp浏览器提交JSON数据请求服务器,服务器调用在线编译模块编译,把结果返回给浏览器

在这里插入图片描述

  • Json如何从req请求中获取到Json请求?
  • 从req对象中获取到。
  • Json如何和Http协议结合?
  • 需要的请求格式是json格式,HTTP能够提供的格式,是另外一种键值对的 格式,所以要对HTTP提供的格式进行格式的转换。
  • 此处由于提交的代码中可能会包含一些特殊符号,这些特殊符号要正确传 输时,就会进行urlencode,这一步由浏览器自动完成。
  • 服务器收到请求之后的第一件事就是切分键值对,再urldecode,然后解> 析数据,整理成需要的Json格式。
  • Json如何进行解析和构造?
  • 使用jsoncpp第三方库。

jsoncpp第三方库获取办法: 在这里插入图片描述 在这里插入图片描述

     1	#include 
     2	
     3	#include "httplib.h"
     4	#include "compile.hpp"
     5	//#include "jsoncpp/json/json.h"
     6	
     7	#include
     8	
     9	int main()
    10	{
    11	   using namespace httplib;
    12	
    13	    Server server;
    14	
    15	    // Get注册一个回调函数,这个函数的调用机制是处理Get方法时
    16	    // lambda表达式 就是一个匿名函数
    17	    
    18	    // 路由过程
    19	    // 接收请求对象,根据请求进行处理,并且将响应返回给客户端
    20	    //
    21	    // 此处get改成post,代码放到body里面
    22	    server.Post("/compile", [](const Request& req, Response& resp) {
    23	        // 根据具体的问题场景,根据请求,计算出响应结果
    24	        (void)req;
    25	
    26	        // 如何从req请求中获取到Json请求
    27	        // Json如何和Http协议结合
    28	        
    29	        // 需要的请求格式是json格式,HTTP能够提供的格式,是另外一种键值对的格式,所以要对HTTP提供的格式进行格式的转换
    30	        
    31	        // 此处由于提交的代码中可能会包含一些特殊符号,这些特殊符号要正确传输时,就会进行urlencode,这一步由浏览器自动完成
    32	        // 服务器收到请求之后的第一件事就是切分键值对,再urldecode,然后解析数据,整理成需要的Json格式
    33	        
    34	        // 此函数将Http中的body,解析成键值对,存入body_kv
    35	        std::unordered_map body_kv;
    36	        UrlUtil::ParseBody(req.body, &body_kv);
    37	
    38	        // Json如何进行解析和构造? 使用jsoncpp第三方库
    39	        // 
    40	        // 下方调用CompileAndRun
    41	        
    42	        Json::Value req_json;   // 从req对象中获取到
    43	
    44	 /*       for(std::unordered_map::iterator it=body_kv.begin();it!=body_kv.end();++it)
    45	        {
    46	            req_json[it->first]=it->second;
    47	        }
    48	*/
    49	
    50	        for (auto e : body_kv)
    51	        {
    52	            // e的类型和 *it 是一致的
    53	            req_json[e.first] = e.second;
    54	        }
    55	
    56	        Json::Value resp_json;  // resp_json发到响应中
    57	
    58	        // resp_json 输出型参数
    59	        Compiler::CompileAndRun(req_json, &resp_json);
    60	
    61	        // 把Json::Value对象序列化成为字符串,才能返回
    62	        Json::FastWriter writer;
    63	        resp.set_content(writer.write(resp_json), "text/plain");
    64	    });
    65	
    66	    // 让浏览器能访问到一个静态页面
    67	    // 静态页面: index.html 不会发生变化
    68	    // 动态页面: 编译结果 随着参数的不同而发生变化
    69	    //
    70	    // 加上这个目录是为了浏览器能够访问到静态页面
    71	    server.set_base_dir("../wwwroot", "");
    72	    server.listen("0.0.0.0", 9092);
    73	
    74	    return 0;
    75	}

在这里插入图片描述 在这里插入图片描述

4.util.hpp工具类 1.TimeUtil类时间戳获取工具TimeUtil标识文件的不同
   18 class TimeUtil
   19 {
   20 public:
   21     // 获取当前时间戳
   22    static int64_t TimeStamp()
   23    {
   24        struct timeval tv;
   25        ::gettimeofday(&tv, nullptr);
   26 
   27        return tv.tv_sec;
   28    }
   29 
   30    static int64_t TimeStampMS()
   31    {
   32        struct timeval tv;
   33        ::gettimeofday(&tv, nullptr);
   34 
   35        return tv.tv_sec * 1000 + tv.tv_usec / 1000;
   36    }
   37 };

在这里插入图片描述

2.打印日志的工具
    39	
    40	// 打印日志的工具
    41	
    42	// 期望打印出的日志格式: 
    43	//      [I时间戳 util.hpp:31] hello
    44	// 日志的使用方式形如: LOG(INFO)             
关注
打赏
1664288938
查看更多评论
0.0551s