1. 程式人生 > >命令下發--html通過CGI與使用者程序互動

命令下發--html通過CGI與使用者程序互動

寫在最前面

華清遠見教育集團
15年專注高階IT培訓
做良心教育,做專業教育,做受人尊敬的職業教育

創客學院官網:http://www.makeru.com.cn/
華清遠見創客學院嵌入式課程連結:http://www.makeru.com.cn/emb
華清遠見創客學院物聯網課程連結:http://www.makeru.com.cn/iot

 

正文

 

在本文介紹的倉儲專案中,使用者通過客戶端的一些控制元件實現對向底層硬體傳送指令,這一過程是命令資料的下發;使用者還可以實時檢視到倉庫的環境資料,這是資料的上報。總體上分為三個的物件和兩條資料流向,網頁端-伺服器-底層實現命令資料的下發和環境資料的上報,也就實現了人機互動的過程。下面是命令下發部分框圖:

 

目的:完成html 和 CGI 和 使用者程序 的互動,實現命令下發並接受到返回結果。隨便從程式上加以分析這一過程。

 

  • HTML(超文字標記語言):就是一種標籤語言,用來描述資源的。加上CSS渲染,就可以通過瀏覽器看到成精美的頁面了。
  • CGI:簡單理解是使用者程序對html實現的一組介面。
  • 使用者程序:使用者程式在系統上的的執行結果。

 

 


實現步驟


1.實現html檔案,放在boa伺服器的www目錄下
2.實現.cgi程式,放在boa伺服器的www目錄下
3.編寫應用程式訊息佇列處理部分,實現與cgi進行互動
4.在開發板上執行boa伺服器,執行應用程式
5.測試結果

關於訊息佇列的使用,我之前寫過一篇介紹:https://mp.csdn.net/postedit/81412616

 

 

 

 


原始碼分析

 

 

1.html  main.html

 

在瀏覽器中右鍵檢視原始碼,顯示如下內容。程式碼的意思是使用者點選提交按鈕,即提交表單資料到boa伺服器目錄的cgi-bin/setEnv.cgi處理。


    <form action="cgi-bin/setEnv.cgi" method="get"><input name="store" type="hidden" value="1" />
      	<tr>
          <th height="55"><div align="center">
	            <label>最高溫度:
	              <input  type="text" name="temMAX" id="textfield"  width="50" maxlength="50" size="10" style="height:10"height="10" onFocus="if(this.value=='*'){this.value='';}" value='50' />
                </label>
	          </div></th>
          <th><div align="center">
	            <label>最高溼度:
	              <input type="text" name="humMAX" id="textfield3" width="50" size="10" style="height:10"height="10" onFocus="if(this.value=='*'){this.value='';}" value='50'/>
                </label>
	          </div></th>
          <th><div align="center">
	            <label>最高光度:
	              <input type="text" name="illMAX" id="textfield5" width="50" size="10" style="height:10"height="10" onFocus="if(this.value=='*'){this.value='';}" value='500'/>
                </label>
	          </div></th>
         </tr>
         <tr>
          <th height="55"><div align="center">
	            <label>最低溫度:
	              <input type="text" name="temMIN" id="textfield2"  width="50" size="10" style="height:10"height="10" onFocus="if(this.value=='*'){this.value='';}" value='5'/>
                </label>
	          </div></th>
          <th><div align="center">
	            <label>最低溼度:
	              <input type="text" name="humMIN" id="textfield4"  width="50" size="10" style="height:10"height="10" onFocus="if(this.value=='*'){this.value='';}" value='10'/>
                </label>
	          </div></th>
          <th><div align="center">
	            <label>最低光度:
	              <input type="text" name="illMIN" id="textfield6"  width="50" size="10" style="height:10"height="10" onFocus="if(this.value=='*'){this.value='';}" value='10'/>
                </label>
	          </div></th>
         </tr>
         <tr>
          <th height="50" colspan="3"><div align="center">
	              <input type="reset" name="button7" style="background-color:transparent" id="button7" value="重置" />
	              <input type="submit" name="button8" id="button8" value="提交"  style="background-color:transparent"/>
                </div></th>
          </tr>
      </form>

 

2.cgic  setenv.c

使用者提交表單,執行到這個介面。cgic使用c語言進行實現,一方面從使用者提交的表單資料中提取到有效的命令資料,將資料內容放在一個訊息結構體msg_buf中;另一方面通過訊息佇列實現與使用者程序/執行緒間的互動。最後將結果一html檔案的形式返回瀏覽器。

 

#define N 32

struct msg
{
	long type;
	long msgtype;
	unsigned char text[N];
};

struct setEnv
{
	int temMAX;
	int temMIN;
	int humMAX;
	int humMIN;
	int illMAX;
	int illMIN;
};

int cgiMain()
{
	key_t  key;
	char sto_no[2];
	char buf[20];
	struct setEnv new;
	int msgid;
	struct msg msg_buf;
	
	memset(&msg_buf,0,sizeof(msg_buf));
	cgiFormString("store", sto_no, 2);

	cgiFormString("temMAX", buf, 20);    //通過cgic.c提供的介面函式 提取表單資料
	new.temMAX = atoi (buf);
	cgiFormString("temMIN", buf, 20);
	new.temMIN = atoi (buf);
	cgiFormString("humMAX", buf, 20);
	new.humMAX = atoi (buf);
	cgiFormString("humMIN", buf, 20);
	new.humMIN = atoi (buf);
	cgiFormString("illMAX", buf, 20);
	new.illMAX = atoi (buf);
	cgiFormString("illMIN", buf, 20);
	new.illMIN = atoi (buf);



	if((key = ftok("/app", 'g')) < 0)
	{
		perror("ftok");
		exit(1);
	}

	if((msgid = msgget(key, 0666)) < 0)
	{
		perror("msgget");
		exit(1);
	}
	
	memcpy (msg_buf.text+1, &new, 24);
	
	msg_buf.type = 1L;
	msg_buf.msgtype = 5L;
	msg_buf.text[0] = sto_no[0];
	
	msgsnd(msgid, &msg_buf,sizeof(msg_buf)-sizeof(long),0);    //訊息佇列與應用程序/執行緒互動

	sto_no[0] -= 48;
	
	cgiHeaderContentType("text/html\n\n");         //成功結果通過html檔案的形式返回
	fprintf(cgiOut, "<HTML><HEAD>\n"); 
	fprintf(cgiOut, "<TITLE>My CGI</TITLE></HEAD>\n"); 
	fprintf(cgiOut, "<BODY>"); 

	fprintf(cgiOut, "<H2>send sucess</H2>");

	//fprintf(cgiOut, "<a href='.html'>返回</a>"); 
	fprintf(cgiOut, "<meta http-equiv=\"refresh\" content=\"1;url=../main%d.html\">", sto_no[0]);
	fprintf(cgiOut, "</BODY>\n"); 
	fprintf(cgiOut, "</HTML>\n"); 


	return 0; 

}

 

 

3.使用者處理程式

下面是使用者主程序中排程的一個執行緒,處理訊息佇列中的請求執行緒。執行緒中一直阻塞等待請求,當從佇列中接收到訊息,表示“我收到了”,然後進行命令的型別判斷,做相應的處理。由於底層還沒有實現,這裡就僅簡單的列印處理


void *pthread_client_request (void *arg)
{
	printf("pthread_client_request\n");

	if((key = ftok("/tmp",'g')) < 0){
		perror("ftok failed .\n");
		exit(-1);
	}

	msgid = msgget(key,IPC_CREAT|IPC_EXCL|0666);
	if(msgid == -1)	{
		if(errno == EEXIST){
			msgid = msgget(key,0777);
		}else{
			perror("fail to msgget");
			exit(1);
		}
	}
	printf("pthread_client_request\n");
	
	while(1){
		bzero(&msgbuf,sizeof(msgbuf));
			printf("wait form client request...\n");
		msgrcv (msgid, &msgbuf, sizeof (msgbuf) - sizeof (long), 1L, 0);
		printf ("Get %ldL msg\n", msgbuf.msgtype);
		printf ("text[0] = %#x\n", msgbuf.text[0]);

		//1L - 5L為執行緒分類的訊息型別
		switch(msgbuf.msgtype){
			case 1L:
					printf("hello led\n");
				break;
			case 2L:
					printf("hello beep\n");
				break;
			case 3L:
					printf("hello seg\n");
				break;
			case 4L:
					printf("hello fan\n");
				break;
			
			case 5L:
					printf("set env data\n");
					printf("temMAX: %d\n",*((int *)&msgbuf.text[1]));
					printf("temMIN: %d\n",*((int *)&msgbuf.text[5]));
					printf("humMAX: %d\n",*((int *)&msgbuf.text[9]));
					printf("humMAX: %d\n",*((int *)&msgbuf.text[13]));
					printf("illMAX: %d\n",*((int *)&msgbuf.text[17]));
					printf("illMAX: %d\n",*((int *)&msgbuf.text[21]));

				break;
			case 6L:
					pthread_mutex_lock(&mutex_led);
					pthread_cond_wait(&cond_led,&mutex_led);
					printf("hello led\n");
					pthread_mutex_unlock(&mutex_led);
					pthread_cond_broadcast(&cond_led);
				break;
			case 10L:
				{
					int i = 0 , j = 0 ;
					for(i = 0 ; i < 11; i++){
						recive_phone[i] = msgbuf.text[i]; 	
					}
					recive_phone[i] = '\0';
					printf("recive:%s\n",recive_phone);
					for(j = 0 ;msgbuf.text[i] != '\0' && j < 12; i++, j++)
					{
						center_phone[j] =  msgbuf.text[i];
					}
					center_phone[j] = '\0';
					printf("center:%s\n",center_phone);

				 }
				break;
			default:
				break;
				
		}
	}

}