(被迫参加的hackathon) 在线编译系统开发小记
[ ]The content is recoverd from Wordpress Blog, for more details please check HERE
November 11, 2015
吐槽
因为某种原因我没有参加MSC举办的Hackathon, 不过我的部员们参加了 0.0 然后我本来想去蹭点Pizza之类的东西吃,结果(我感觉他们是给我诱拐过去了) 到了比赛现场之后告诉我, 这里封馆了 Orz 于是乎我就被迫开始写代码(连电脑都没有带只为了去蹭口pizza吃的我TAT[结果最后还没吃到pizza])
实现的是一个简单的在线编译系统 TOC (Toy Online Compiler) 支持多种语言, 下面简单说一下实现的思路和核心的代码
实现思路
简单分析一下这个系统,由两部分组成 ,代码提交模块和代码编译运行模块 ,前者负责将代码交给后者,后者编译运行完毕将结果返回给前者,然后前者将结果展示给用户.
具体实现方式是: 代码提交模块负责将代码文件保存到服务器, 然后通过socket将消息通知到代码编译模块,然后代码编译模块执行完毕的结果再通过通信的方式传递回来, 很显然实现代码提交模块实现难度很容易,主要的问题在后者的编译模块的通信和编译问题, 下面给出编译模块的核心代码
<?php
error\_reporting(E\_ALL);
require\_once('function.php');
require\_once('queue.php');
require\_once('actionclass.php');
$socketQueue = new actionQueue();
$socketQueue->initQueue();
$mainSocket = SocketOpen();
socket\_set\_option($mainSocket, SOL\_SOCKET, SO\_REUSEADDR, 1);
while(TRUE)
{
if($socketQueue->len > 5)//Maximum count
continue; //Do not accept create new socket
$resSocket = socket\_accept($mainSocket);
if($resSocket != FALSE)
{
$socketQueue->push($resSocket);
}
if($socketQueue->isempty() The content is recoverd from Wordpress Blog, for more details please check [HERE](recover-my-blog) FALSE)
{
$currentSocket = $socketQueue->pop();
$rawMsg = SockRead($currentSocket);
echo "Raw Msg is $rawMsgn";
if(Auth($rawMsg) The content is recoverd from Wordpress Blog, for more details please check [HERE](recover-my-blog) true)
{
$actionObj = ParseMsg($rawMsg);
$simpleResultObj = $actionObj->Compile();
if($simpleResultObj->resultno != 0)
{
echo "Compile Errorn";
SockWrite($currentSocket, "ERR");
SockWrite($currentSocket, $simpleResultObj->resultStr);
}
else
{
echo "Compile OKn";
SockWrite($currentSocket, "OK");
$simpleResultObj = $actionObj->Run();
//Send Msg back to client
if($simpleResultObj->resultno The content is recoverd from Wordpress Blog, for more details please check [HERE](recover-my-blog) 0)
{
SockWrite($currentSocket, "OK");
SockWrite($currentSocket, $simpleResultObj->resultStr);
}
else
{
SockWrite($currentSocket, "ERR");
SockWrite($currentSocket, $simpleResultObj->resultStr);
}
}
}
else
{
$getaddr = "";
$getport = "";
socket\_getsockname($currentSocket, $getaddr, $getport);
echo "Invalid request from $getaddr:$getport";
SockWrite($currentSocket, "FATAL");
}
}
}
这段代码就是编译模块的核心逻辑, 我使用了一个队列来维护所有在队列内的通信, 队列最多有5个元素, 代码运行起来会持续检查队列是否为空,如果队列不为空,就会取出队列头的socket,处理socket传来的消息,编译相应的代码,然后产生结果通过封装好的socket_write SockWrite,将运行结果回传给代码提交模块,重复上述操作.
为了保证代码的可读性, 封装了一个编译类 actionClass 来进行编译和运行, 编译和运行的方式是通过exec调用系统命令,下面会具体说明
实现细节
- 编译和运行的方式是使用exec调用系统指令, exec指令可以直接将执行结果作为返回值,不过他的结果只能返回stdout里的内容,stderr的内容不能返回, 因此我使用的方式是 将stderr的内容重定向到文件 cerr.txt 然后检测此文件是否为空, 如果不为空的话说明出错了
- 不过在最初实现的时候出现了这样的问题, 当你提交一个编译错误的代码之后,再提交一个可以正常运行的代码,编译模块仍然会报编译错误, 而如果手动查看这个文件发现这个文件大小为0 , 通过打印filesize(“cerr.txt”)的返回值,发现了 filesize的返回值不为0 ,但是此时cerr.txt文件大小为0 (du -h cerr.txt ) 查资料发现, filesize 的结果会调用缓存的结果 “Note: The results of this function are cached. See clearstatcache() for more details.“[php.net 原文] . 因此在每次取得filesize之后, 都要使用clearstatcache()将之前的状态清除掉
- 另外遇到的一个问题就是在停止掉后端编译模块之后, 再次启动这个模块会报错 Unable to bind , address already in use , 这个问题在php.net 的官网也有说明
If you want to reuse address and port, and get rid of error: unable to bind, address already in use, you have to use socket_setopt (check actual spelling for this function in you PHP verison) before calling bind:
设置上 SO_REUSEADDR
- 另外代码运行时限是使用Linux中的timeout的功能实现的
- 当程序执行结果为空的时候(不产生任何输出) 代码提交模块会一直在socket_read()处等待到来消息, 因此通过自己实现了封装好的SockRead和SockWrite 来避免这个问题
目前实现阶段
- 支持PHP C++ C Python Ruby 的编译(解释)运行
- 可以在Raspberry Pi上搭建整个系统
待解决问题
- 编译时使用sandbox来保证安全性 , 暂定使用chroot来实现sandbox功能
- 登录和注册没有完全实现
- 将这个代码布置到拥有防火墙的CentOS服务器上, 两个模块之间不能互相通信(这个问题一直还没解决)
PHP, Web Develop C. Linux, kernel, Laravel, PHP, Python, Shell, Web, wine
Historical Comments
Post navigation ————— NEXT
setcap wine 遇到的问题解决 PREVIOUS [Laravel] 配置phpstorm支持laravel语法补全 Comments are closed.
统计信息nanodesu~~~
当前在线人数 (。・ω・)ノ゙ 0
修罗酱真诚欢迎更多的朋友来我的WOWO做客哦~ Search for: Search #### Recent Posts
- Customize Your Zsh Prompt
- 将 vim 作为日常笔记本使用
- Running Arch Linux with customized kernel in QEMU
- proxychains-ng 原理解析
- 闭关三月 博客之后更新
Recent Comments
- VOID001 on 将 vim 作为日常笔记本使用
- VOID001 on 留言板
- Jim Yu on 留言板
- VOID001 on VOID
- muou333000 on 将 vim 作为日常笔记本使用
友情链接
YongHao Hu’s Blog
亿臻的知乎主页(非个人博客站点)
yungkcx’s Blog
Asm Def
Five Yellow Mice’s Blog(一个ruby&php dalao)
老K(csslayer)的另一个博客
Solomon(萌萌的Poi的自制博客~)
Farseerfc的小窩(ArchLinux TU ~ 可爱的爱呼吸酱)
Sherlock-Holo的博客~(夏狼好可爱!)
KK的博客~(前辈好OwO)
智乃酱(Frantic1048)的博客~(萌萌的智乃> <)
No Silver Bullet | LA
的博客=w=
某兔子の御用花园 | 喵兔的博客\w/
千千blog (萌千千=w
Typeblog | 彼得彼得的博客w
静静’s Blog | 好耶w
南浦月 | 乔姐姐老师的博客
初等記憶體 | 艾雨寒的博客
It’s Kiri~!! | Kiriririri 的博客
失う | Equim 酱的博客~ 是 Gopher 呢
Makito’s Notebook | 是可爱的 Android Dev Makito 呢~~ (吸吸)
灰灰,可爱的男孩纸
DuckSoft’s Blog | Ex nihilo ad astra
Leo’s Field, 一位 UW 的数学系大大!Archives
- June 2019
- February 2019
- January 2019
- August 2018
- January 2018
- November 2017
- September 2017
- July 2017
- June 2017
- May 2017
- April 2017
- March 2017
- February 2017
- January 2017
- December 2016
- November 2016
- October 2016
- September 2016
- August 2016
- July 2016
- June 2016
- May 2016
- April 2016
- March 2016
- February 2016
- January 2016
- November 2015
- October 2015
- September 2015
- August 2015
- May 2015
- April 2015
- March 2015
- February 2015
- January 2015
- December 2014
- November 2014
- October 2014
- September 2014
- August 2014
Categories
- ACM Algorithm
- AI
- Android
- archlinux
- C
- DynamicProgramming
- emacs
- gcc
- golang
- GraphTheory
- hash
- Kernel
- Kernel
- Linux
- Linux_Basis
- LuaSource
- Minecraft
- Number Theory
- PHP
- Projects
- Robocode~
- Ruby
- STL
- Threads and Process
- Uncategorized
- vim
- Vocaloid
- Water
- Web Develop
- wine
- 基础网络知识
- 文章转载
- 杂七杂八
- 计算机系统原理
- 计算机网络
Tags
archlinux C C. Linux kernel Laravel linux os PHP prompt Python qemu rtmp Shell video vim Web wine zsh © 2020 | Proudly Powered by WordPress | Theme: Nisarg /* <![CDATA[ / var screenReaderText = {“expand”:”expand child menu”,”collapse”:”collapse child menu”}; / ]]> / / <![CDATA[ /EnlighterJS_Config = {“selector”:{“block”:”pre.EnlighterJSRAW”,”inline”:”code.EnlighterJSRAW”},”language”:”generic”,”theme”:”git”,”indent”:2,”hover”:”hoverEnabled”,”showLinenumbers”:true,”rawButton”:true,”infoButton”:true,”windowButton”:true,”rawcodeDoubleclick”:true,”grouping”:true,”cryptex”:{“enabled”:false,”email”:”[email protected]”}};!function(){var a=function(a){var b=”Enlighter Error: “;console.error?console.error(b+a):console.log&&console.log(b+a)};return window.addEvent?”undefined”The content is recoverd from Wordpress Blog, for more details please check HEREtypeof EnlighterJS?void a(“Javascript Resources not loaded yet!”):”undefined”The content is recoverd from Wordpress Blog, for more details please check HEREtypeof EnlighterJS_Config?void a(“Configuration not loaded yet!”):void window.addEvent(“domready”,function(){EnlighterJS.Util.Init(EnlighterJS_Config.selector.block,EnlighterJS_Config.selector.inline,EnlighterJS_Config)}):void a(“MooTools Framework not loaded yet!”)}();;/ ]]> */