You are on page 1of 10

东华大学计算机科学与技术学院课外科技活动实验报告

基于 Ajax 的 C 语言 在线

解释环 境 WebC 的设计 与实现

姓名:钟芸龙
东华大学计算机科学与技术学院课外科技活动实验报告

学号:050950225

指导老师:姚砺
东华大学计算机科学与技术学院课外科技活动实验报告

实验 要求

设计并实现一个简单的在线 C 语言解释系统,受 Lua 官方网站的 Demo 启发,此系统可

以完成各种可以方便同学在手头没有编译环境的情况(如网吧),完成简单的 C 程序的测

试工作。用户只需输入 C 语言源代码和输入数据(如果没有可以留空),按一下运行按钮

就可以提交至服务器执行,服务器返回最终程序的输出。

相关 技术说 明

Ajax( Asynchronous JavaScript And XML)

传统的 web 应用允许用户填写表单 (form),当提交表单时就向 web 服务器发送一个请

求。服务器接收并处理传来的表单,然後返回一个新的网页。这个做法浪费了许多带宽,因

为在前後两个页面中的大部分 HTML 代码往往是相同的。由于每次应用的交互都需要向服

务器发送请求,应用的响应时间就依赖于服务器的响应时间。这导致了用户界面的响应比本

地应用慢得多。

与此不同, AJAX 应用可以仅向服务器发送并取回必需的数据,它使用 SOAP 或其它

一些基于 XML 的 web service 接口,并在客户端采用 JavaScript 处理来自服务器的响应。因

为在服务器和浏览器之间交换的数据大量减少,结果我们就能看到响应更快的应用。同时很

多的处理工作可以在发出请求的客户端机器上完成,所以 Web 服务器的处理时间也减少了。

jQuery

jQuery 是继 prototype 之后又一个优秀的 Javascript 框架。其宗旨是写更少的代码,做更多

的事情。

它是轻量级的 js 库(压缩后只有 21k) ,这是其它的 js 库所不及的,它兼容 CSS3,还兼


东华大学计算机科学与技术学院课外科技活动实验报告

容各种浏览器 (IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+)。

jQuery 是一个快速的,简洁的 javaScript 库,使用户能更方便地处理 HTML documents、

events、实现动画效果,并且方便地为网站提供 AJAX 交互。

Kepler

本着轻量简单的原则,我摒弃了目前主流的 Apache,IIS 等服务器,以及相关的后台的脚

本语言解释器如 PHP 解释器等,而是使用了基于 Lua 的网站开发框架 Kepler,此系统非常

轻巧,其安装软件仅有七百多 k,就已经把 Web 服务器,脚本解释器和数据库套件都包含

了。

Kepler 的模块虽小,但功能非常完善,其本身是一个强大的模块化的系统,由若干个

Lua 模块组成,而且在 Linux 平台上还提供了一个相当于 Ruby 的 gem 的东西:Lua Rocks,

可以非常方便地安装,查询和卸载 Lua 模块。

JSON
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同

时也易于机器解析和生成。它基于 JavaScript ( Standard ECMA-262 3rd Edition - December

1999)的一个子集。 JSON 采用完全独立于语言的文本格式,但是也使用了类似于 C 语言

家族的习惯(包括 C, C++, C#, Java, JavaScript, Perl, Python 等)。这些特性使 JSON 成为理

想的数据交换语言。

在基于 Ajax 的网站中,虽然很多数据交换格式是 XML,但是 XML 本身是一个严格的

标记语言,相对而言难以解析,而且冗余信息多,带宽占用也多一些,对于交互性较多的

Ajax 应用来说,JSON 是比 XML 更经济的选择。


东华大学计算机科学与技术学院课外科技活动实验报告

设计 思想

WebC 是一个简单的 C 语言在线解释环境,它后台使用 Fabrice Bellard 的 TCC(Tiny C

Compiler)作为 C 语言的解释器,TCC 既可以将 C 语言编译成二进制代码,也可以直接将其

解释执行,这是 TCC 最富有特色的功能之一,也是之所以将此工具用于 WebC 的后台解释

器的原因。

WebC 基于 B/S 架构,与传统的 B/S 不一样的是,它引入了目前流行的 Ajax 技术,但

没有直接使用 XMLHttpRequest 对象,因为这样太繁琐了,而且对于不同的浏览器,还要

许多解决兼容性问题的代码,于是我采用了 jQuery 这一流行的 Ajax 框架,jQuery 可以大大

地简化代码的编写。

使用 Ajax 技术后,服务器只返回浏览器所必需的数据,从而可以减少延迟。另外,返

回给浏览器的数据是以 JSON 而不是 XML 格式,这又进一步减少了延迟。

下面两图分别描述了总体过程:

图 1 WebC 的运行 流程
服务器端运行程序是通过将客户端提交的 C 代码写入到一个临时文件,然后解释之,

并将其错误输出重定向,但运行程序的标准输出则是直接用管道来读取,并最终传回给浏

览器。下图就是服务器端的处理流程:
东华大学计算机科学与技术学院课外科技活动实验报告

图 2 服务器 端的 处
理流程
服务器端具

体的执行的命令

tcc -run C 源

文件 < 输入文件

2>错误输出文件

这里三个文

件都是临时文件,

它们都是在处理

同一次请求时生

成的,在响应完

成后会立即清除。

其中用到了重定

向这一方法,其

中小于号<的作用

是指定程序运行的输入,2>是指定程序的错误输出。重定向用来把原来从键盘读入的内容

可以从文件里读入,也可以将原本输出到屏幕里的内容输出到文件里,这样的好处是可以

将大量本身需要人工处理的数据,在文件里弄好,实现了自动化。在 UNIX 系统里,标准输

入文件的文件描述符是 0,标准输出是 1,标准错误输出是 2(所以错误输出重定向的写法

是 2>),这三个都是程序启动时自动设定好的。在 Windows 的命令行提示符里,也可以兼

容 POSIX 的写法。

至于管道,是指将程序的标准输出连接到另外一个程序的标准输入,这样可以将本来

需要一个复杂的处理过程分解成若干个原本单个程序就可以处理的问题,是 UNIX 脚本自

动化的一个重要技术。在 C 语言的标准库里,有一个 popen 函数,就可以打开一个管道,可

以像从普通文件一样读取程序的标准输出。相对于临时的磁盘文件来说,管道的读取效率要

高一些,因为它的数据传递都是在内在中完成的,因此在我的程序时,我没有把标准输出
东华大学计算机科学与技术学院课外科技活动实验报告

重定向到临时文件,而是从管道里读取的,虽然重定向也是可行的,但是从管道读取效率

应该更高。

在浏览器端,我使用了 jQuery,jQuery 真是一个奇妙的 JavaScript 库,它不仅仅是一个

Ajax 框架,而且在很多方面已经改变了 JavaScript 传统的编程方法。如通常使用 DOM 来获

取元素引用:

document.getElementById("id")

使用 jQuery 后,就可以用简单得多的$("#id")来代替了,此函数返回的是一个 jQuery

对象,可以通过调用它的 attr 来获取和设置属性,val 来获取和设置内容,css 来获取和设

置样式,使用起来颇为方便。

jQuery 里提供了一个$.ajax 方法,是处理 Ajax 应用的一把利器,它使用

XMLHttpRequest 对象,对于浏览器的不兼容性问题做了包装,比直接利用

XMLHttpRequest 对象来处理方便了不少,当然,这层层包装的后果当然造成了效率的降低,

不过由于 WebC 本身应用并不复杂,所以效率的降低基本觉察不到。

下面是与服务器进行交互的关键 JavaScript 代码:

function RunCode(){

var code=$("#code").val(); //获取代码文本框的内容

if(code==""){

alert("Please write some code in the code form!"); //若为空,则提醒用户填写代

return;

$("#run").attr("disabled","disabled"); //暂时禁用按钮

$.ajax({
东华大学计算机科学与技术学院课外科技活动实验报告

url:"run.lua", //请求网址,用于处理浏览器的请求

type:"POST", //POST 方式,由于代码可能很长,只能用这种方式

data:{ code:code,input:$("#input").val()}, //发送的数据

dataType:"json", //使用 JSON 作为服务器返回结果的封装格式

success:function(result){

var output=$("#output");

if(result.error){

output.css("color","red");

output.css("font-weight","bold");

output.val(result.error);//若出现错误,则以红色粗体显示在输出框里

}else{

output.css("color","black");

output.css("font-weight","normal");

output.val(result.output); //正常时直接显示

$("#run").attr("disabled","");//启用按钮

$("#usedtime").html("Used time: <b>"+result.time+"</b> seconds");

//显示服务器运行此程序的时间

})

}
东华大学计算机科学与技术学院课外科技活动实验报告

使用 手册

由 于 WebC 是 B/S 架 构 , 先 要 启 动 Web 服 务 器 , Kepler 套 件 中 的 Web 服 务 器 名 为

Xavante,是巴西的一个民族的名字。启动以后会在系统托盘显示一个绿色的图标:

图 3 系统 托盘 里的 Xavante 图标

然后启动浏览器,在浏览器的地址栏输入相应的地址:

图 4 在浏 览器 的地 址栏 里填 入地 址

在出现的页面的 Code 框里填入要运行的 C 代码,然后按下下面的“ Run” 按钮,服务通

过解释运行后,最终在浏览器的 Output 框里显示出来:

图 5 在 Code 框里 填入

C 源代 码

图 6 在 Output 框里 显示 出程 序运

行结果

如果程序还需要输入,则在

Input 框里输入要输入的文字:

图 7 在 Input 框里填 入要 输

入的 文字

如果编译出错,则在
东华大学计算机科学与技术学院课外科技活动实验报告

Output 中会以红色粗体字显示编译出错信息:

图 8 如果出 错, 会

在 Output 里显 示

出错误 信息

程序 的不足 与可完 善之处

由于时间仓促,此系统还有很多不足的地方,主要有以下几点:

 没有检测程序本身的问题,而只是简单地执行之,这样危险的程序会给服务器带来严

重的后果。另外由于目前 WebC 过于简单,也没能返回程序的内存使用量等有用信息。

我目前想到的一个方法不是将其解释执行,而是用 GCC 编译之,在编译过程中加入调

试信息,然后使用调试器 gdb 来运行。

 管道的利用不足,仅仅利用其读取标准输出,现在从 Lua 的标准库里我暂时还没有找

到打开可同时读写的管道的方法,用 io.popen 方法不行。这样导致服务器会频繁地读写

临时文件。

 没有分析错误输出,而是直接返回给浏览器,而原始的错误输出内容使用的是临时文

件名,这样显得不大好。

 程序还可以加入预期输出内容框,放在浏览器端,当输出数据比较复杂时,可以减轻

比对工作的繁琐。

 返回的运行时间只精确到了秒,这个精度实在是太“粗”了。

 临时文件的命名是使用当前的秒数,这极有可能在不同的机器在同一秒内请求同一个

服务器时出现冲突。

You might also like