05
29

Embedded AJAX+CGI web UI solution

最近抓了一些網路設備的open source來trace,發現有些網路設備的web UI有用到AJAX,也就是在他網頁原始碼可以很清楚看到onreadystatechange所指到的回呼函式,小弟在trace完大部份的code以後,簡單整理如下

CGI
原理解說



CGI為一通訊轉換的界面供ClientServer交換它們的資料流,client的資料(POSTDATA,QUERY STRING)進來時,會被CGI轉換成STREAM型態的資料並送到STDINSERVER讀取,同樣的,Server寫在stdout的資料同樣會被CGI轉換成資料(or 封包)的形態丟給client
讀取

AJAX
原理解說

AJAX在我觀念裡它實在很像ISR(interrupt service routine),簡單的來說,我的函式只要可以跟kernel某個事件註冊,kernel事件發生時,會主動呼叫我的函式,AJAX也是一樣,client要求的資料送達了,系統會主動呼叫client端註冊的資料處理函式,而不用我們人為在網頁上做refresh
的動作

Client端的web頁面重點解說
<script>
var myxml
function createXMLHttpRequest() {
    
var xmlHttp;
    
if (window.XMLHttpRequest) { //if we can get XMLHttpRequest
        
xmlHttp = new XMLHttpRequest()// Mozilla、Firefox、Safari
    
}
    
else if (window.ActiveXObject) { //if we can get ActiveXObject
        
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); // Internet Explorer
    
}
    
return xmlHttp
}
 
function handleGetStateChange() {
  
if (myxml.readyState == 4) {
    
if (myxml.status == 200) {
          
//alert("Server Response" + myxml.responseText);
      
document.GetVal.t1.value=myxml.responseText 
    
}
  
}
}
function startGetRequest()
{
    
    
myxml=createXMLHttpRequest();
    
if (!myxml) alert("ajax not supported")
    
myxml.onreadystatechange = handleGetStateChange;
    
myxml.open("GET", "http://192.168.15.5/cgi-bin/cpe.cgi?freq&username",true)
    
myxml.send("")
}

當送出的button被按下時,此程式會送出GET指令,並把freq和username這兩個參數傳送給Server,並且註冊handleGetStateChange為回呼函式
Server端的CGI處理函式如下
query_string=getenv("QUERY_STRING");
    
    
if (qlen!=0)//deal with method get
    
{
        
        
fprintf(stdout, "Content-Type: text/html\r\n\r\n");
        
        
for(i=0;qlen>0; i++)
    
{
        
inputs[i].val = ReadString(query_string,'&',&qlen);
            
repIndex=i;
            
query_string+=strlen(inputs[i].val)+1;
    
}
        
        
for (i=0;i<=repIndex;i++)
        
{
            
if (strcmp(inputs[i].val,"freq")==0) fprintf(stdout,"%s=%s&",inputs[i].val,freq);
            
if (strcmp(inputs[i].val,"username")==0) fprintf(stdout,"%s=%s&",inputs[i].val,username);
        
}
        
        
return 0;
    
}

Server端的cgi程式會去抓取query string並截取其內的值當做要查尋的value name

Client端web頁面完整的程式碼如下所示
<html>
 
<
head>
 
<
title></title>
<
script>
var myxml
function createXMLHttpRequest() {
    
var xmlHttp;
    
if (window.XMLHttpRequest) { //if we can get XMLHttpRequest
        
xmlHttp = new XMLHttpRequest()// Mozilla、Firefox、Safari
    
}
    
else if (window.ActiveXObject) { //if we can get ActiveXObject
        
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); // Internet Explorer
    
}
    
return xmlHttp
}
 
function handleGetStateChange() {
  
if (myxml.readyState == 4) {
    
if (myxml.status == 200) {
          
//alert("Server Response" + myxml.responseText);
      
document.GetVal.t1.value=myxml.responseText 
    
}
  
}
}
function handleSetStateChange() {
  
if (myxml.readyState == 4) {
    
if (myxml.status == 200) {
        
// alert("Server Response" + myxml.responseText);
          
document.SetVal.t2.value=myxml.responseText
    
}
  
}
}
 
function startGetRequest()
{
    
    
myxml=createXMLHttpRequest();
    
if (!myxml) alert("ajax not supported")
    
myxml.onreadystatechange = handleGetStateChange;
    
myxml.open("GET", "http://192.168.15.5/cgi-bin/cpe.cgi?freq&username",true)
    
myxml.send("")
}
function startSetRequest()
{
 
    
myxml=createXMLHttpRequest();
    
if (!myxml) alert("ajax not supported")
    
myxml.onreadystatechange = handleSetStateChange;
    
myxml.open("POST", "http://192.168.15.5/cgi-bin/cpe.cgi",true);
    
myxml.send("freq=123&username=jim");
}
 
</
script>
</
head>
 
<
body>
<
form name="GetVal">
<
INPUT type="button" value="Get Value" onclick="startGetRequest()">
<
INPUT type="text" name="t1">
</
form>
<
form name="SetVal">
<
INPUT type="button" value="Set Value" onclick="startSetRequest()">
<
INPUT type="text" name="t2">
</
form>
</
body>
</
html>


Server端完整的cgi程式下所示,用gcc -o xxx.cgi xxx.c編成cgi執行檔並丟到你網頁目錄的cgi-bin下執行

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
 
typedef struct {               
    
char *name;                 
    
char *val;                 
} input;
 
FILE *fp, *fopen();
char freq[10]="1.23";
char username[10]="jemic";
 
char *ReadStdin(FILE *f, char stop, int *len)
{
    
int wsize;
    
char *word;
    
int x;
 
    
wsize = 102400;
    
x=0;
    
word = (char *) malloc(sizeof(char) * (wsize + 1));
 
    
while(1) {
        
word[x] = (char)fgetc(f);
        
if( x==wsize) {
            
word[x+1] = '\0';
            
wsize+=102400;
            
word = (char *)realloc(word,sizeof(char)*(wsize+1));
        
}
        --
(*len);
        
if((word[x] == stop) || (feof(f)) || (!(*len))) {
            
if(word[x] != stop) x++;
            
word[x] = '\0';
            
return word;
        
}
        ++
x;
    
}
}
        
char *ReadString(char *f, char stop, int *len)
{
    
int wsize;
    
char *word;
    
int x;
 
    
wsize = 102400;
    
x=0;
    
word = (char *) malloc(sizeof(char) * (wsize + 1));
 
    
while(1) {
        
word[x] = *f;
    
f++;
        
if( x==wsize) {
            
word[x+1] = '\0';
            
wsize+=102400;
            
word = (char *)realloc(word,sizeof(char)*(wsize+1));
        
}
        --
(*len);
        
if((word[x] == stop) || (!(*len))) {
            
if(word[x] != stop) x++;
            
word[x] = '\0';
            
return word;
        
}
        ++
x;
    
}
}
      
 
char *ReadData(char *line, char stop)
{
    
int i = 0, j;
    
char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
 
    
for(i=0; ((line[i]) && (line[i] != stop)); i++)
        
word[i] = line[i];
 
    
word[i] = '\0';
    
if(line[i]) ++i;
    
j=0;
 
    
while(line[j++] = line[i++]);
    
return word;
}
 
int main(int argc, char *argv[])
{
        
input inputs[256];
    
register int i=0;
    
char *query_string=NULL;
    
int len=0,qlen=0,repIndex=0;
    
    
    
qlen=strlen(getenv("QUERY_STRING"));
    
query_string=getenv("QUERY_STRING");
    
    
if (qlen!=0)//deal with method get
    
{
        
        
fprintf(stdout, "Content-Type: text/html\r\n\r\n");
        
        
for(i=0;qlen>0; i++)
    
{
        
inputs[i].val = ReadString(query_string,'&',&qlen);
            
repIndex=i;
            
query_string+=strlen(inputs[i].val)+1;
    
}
        
        
for (i=0;i<=repIndex;i++)
        
{
            
if (strcmp(inputs[i].val,"freq")==0) fprintf(stdout,"%s=%s&",inputs[i].val,freq);
            
if (strcmp(inputs[i].val,"username")==0) fprintf(stdout,"%s=%s&",inputs[i].val,username);
        
}
        
        
return 0;
    
}
        
if (qlen==0)//deal with method set
    
{
        
len = atoi(getenv("CONTENT_LENGTH"));
        
for(i=0;len && (!feof(stdin)); i++)
        
{
                    
inputs[i].val = ReadStdin(stdin,'&',&len);
                    
inputs[i].name = ReadData(inputs[i].val,'=');
            
repIndex=i
            
}
        
fprintf(stdout, "Content-Type: text/html\r\n\r\n");
        
for (i=0;i<=repIndex;i++)
        
{
            
            
if (strcmp(inputs[i].name,"freq")==0)
            
{
                
strncpy(freq,inputs[i].val,10);
                
fprintf(stdout,"%s=%s&",inputs[i].name,freq);
            
}
            
if (strcmp(inputs[i].name,"username")==0)
                        
{
                                
strncpy(username,inputs[i].val,10);
                                
fprintf(stdout,"%s=%s&",inputs[i].name,username);
                        
}
 
        
}
        
        
return 0;
    
}
    
else
    
{
        
fprintf(stdout, "Content-Type: text/html\r\n\r\n");
        
return 0;
    
}
}


標籤: embedded
評論: 0 | 引用: 0 | 閱讀: 6839
發表評論
暱 稱: 密 碼:
網 址: E - mail:
驗證碼: 驗證碼圖片 選 項:
頭 像:
內 容: