Linux下以C构建WEB服务并响应XHR(XMLHttpRequest)请求

本文介绍了一种通过自定义Web服务器处理XHR请求的方法,包括GET和POST请求的处理流程及其实现细节。通过分析请求头、请求体和响应构建过程,展示了如何在服务端解析并响应XHR发送的FormData。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网页要与硬件打交道,通常的方式是使用CGI,那除了CGI之外,还有没有其他的方式呢?我们知道XHR是可以在不提交表单的情况下,实现与WEB服务端的交互的,那么服务端除了CGI来作出响应外,还有没有其他的方法呢?

答案是有的,我们先来看效果图。

1.XHR的POST请求效果图



2.XHR的GET请求效果图



因为WEB的交互在本质上就是HTTP请求,既然是HTTP请求,那么我们只要以HTTP的形式作出回应,那不就可以了吗?

再思考一个问题,XHR请求有两种方式,一种是GET,一种是POST。这和表单的提交方式是相似的。如果有注意观察,就会发现,提交表单时采用GET请求时,表单数据会跟在URL后面,以问号作为开始,并以KEY-VALUE对的形式以&符号分隔多个KEY-VALUE对。而采用POST方法时,则不是这样的。

那POST的数据又是如何提交出去的?服务端收到的数据又会是什么 样的呢?为此,我以C构建了一个简单的WEB服务来响应XHR的POST请求。下面是实现的步骤。

1.在服务端以SOCKET的形式监听服务端口。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:10px;">/* server.c */  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <string.h>  
  5. #include <unistd.h>  
  6. #include <sys/socket.h>  
  7. #include <netinet/in.h>  
  8.   
  9. #define MAXLINE 1024  
  10. #define FILE_NAME_LEN_MAX 256  
  11. #define DEFEULT_SERVER_PORT 8000  
  12. #define RESPONSE_HEADER_LENGTH_MAX 1024  
  13. #define BOUNDARY_LEN_MAX 256  
  14. #define KEY_LEN_MAX 256  
  15. #define VALUE_LEN_MAX 1024  
  16. #define BACK_LEN_MAX 10240  
  17. #define FORM_DATA_LEN_MAX 10240  
  18.   
  19. struct FormData  
  20. {  
  21.   char Key[KEY_LEN_MAX];  
  22.   char Value[VALUE_LEN_MAX];  
  23.   struct FormData *Next;  
  24. };  
  25. char * fetchMethod(const char * buf);  
  26. int hasFormDataInUrl(const char * buf,int bufLen);  
  27. char * fetchFileName(const char * buf,int bufLen);   
  28. char * readFileBytes(const char * fileName);  
  29. char * fetchBoundary(const char * buf,int bufLen);  
  30. void handleFormData(int connfd,const char * buf,const char * boundary,const int isFormDataInUrl/*0:not.1:is*/);  
  31. struct FormData * fetchFormData(const char * buf,const char *boundary);  
  32. struct FormData * fetchFormDataInUrl(const char * buf);  
  33. void responseFormData(int connfd,struct FormData * head,const char *method);  
  34. void response(int connfd,char *responseContent,int responseContentLength,char *responseCode,char *contentType);  
  35.   
  36. int main(int argc, char *argv[])  
  37. {  
  38.     struct sockaddr_in servaddr, cliaddr;  
  39.     socklen_t cliaddr_len;  
  40.     int listenfd, connfd;  
  41.     char buf[MAXLINE];  
  42.     char *data;  
  43.         char *responseContent;  
  44.     char str[INET_ADDRSTRLEN];  
  45.     char *method;  
  46.     char *fileName;  
  47.     char *boundary;  
  48.     int i,n;  
  49.     int port= DEFEULT_SERVER_PORT;  
  50.   
  51.     if(argc>1)  
  52.       {  
  53.         port=atoi(argv[1]);//Input port  
  54.       }  
  55.     if(port<=0||port>0xFFFF)  
  56.       {  
  57.         printf("Port(%d) is out of range(1-%d)\n",port,0xFFFF);  
  58.         return;  
  59.       }  
  60.     listenfd = socket(AF_INET, SOCK_STREAM, 0);  
  61.   
  62.     bzero(&servaddr, sizeof(servaddr));  
  63.     servaddr.sin_family = AF_INET;  
  64.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);  
  65.     servaddr.sin_port = htons(port);  
  66.       
  67.     bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));  
  68.   
  69.     listen(listenfd, 20);  
  70.   
  71.     printf("Listen %d\nAccepting connections ...\n",port);  
  72.     while (1)  
  73.       {  
  74.         cliaddr_len = sizeof(cliaddr);  
  75.         connfd = accept(listenfd,   
  76.                 (struct sockaddr *)&cliaddr, &cliaddr_len);  
  77.         
  78.         n = read(connfd, buf, MAXLINE);  
  79.         printf("---------------------\n");  
  80.         printf("received from %s at PORT %d\n",  
  81.                inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),  
  82.                ntohs(cliaddr.sin_port));  
  83.         printf("read:%d\n%s\n",n,buf);    
  84.               
  85.         method=fetchMethod(buf);  
  86.         printf("method:%s\n",method);  
  87.         if(strcmp(method,"GET")&&strcmp(method,"POST"))          
  88.              {         
  89.           response(connfd,"Only support GET/POST",21,"200 OK","text/html");  
  90.           close(connfd);  
  91.           continue;  
  92.          }  
  93.           
  94.         if(hasFormDataInUrl(buf,n))//Check from data in url  
  95.           {        
  96.             handleFormData(connfd,buf,boundary,1);//Directly response if has form data in url.(GET Method)  
  97.             close(connfd);  
  98.             continue;  
  99.           }  
  100.           
  101.         fileName=fetchFileName(buf,n);  
  102.         printf("Request file name:%s\n",fileName);    
  103.         responseContent=readFileBytes(fileName);      
  104.         if(responseContent)//Response if has content.  
  105.           {  
  106.             //printf("response content:%s\n",responseContent);  
  107.             response(connfd,responseContent,strlen(responseContent),"200 OK""text/html");  
  108.             close(connfd);  
  109.             continue;  
  110.           }  
  111.   
  112.         boundary=fetchBoundary(buf,n);//If no content,web may sumbit form data.Fetch boundary firstly if has form data.  
  113.         if((!boundary)||(strlen(boundary)<=0))//No content and no boundary,file is not exist.  
  114.           {       
  115.             printf("Request file not exist!\n");  
  116.             response(connfd,"404 Not Found",13,"200 OK","text/html");  
  117.             close(connfd);  
  118.             continue;  
  119.           }  
  120.           
  121.         handleFormData(connfd,buf,boundary,0);//POST method.Form data is between boundaries.  
  122.         close(connfd);  
  123.     }  
  124. }</span>  

2.分析请求的方法是否为GET或POST

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. char * fetchMethod(const char * buf)  
  2. {  
  3.   int i;  
  4.   char *method;  
  5.   if(!buf)  
  6.     {  
  7.       return NULL;  
  8.     }  
  9.   method=(char *)malloc(5);  
  10.   memset(method,'\0',5);  
  11.   for(i=0;i<5;i++)  
  12.     {  
  13.       if(buf[i]=='/'||buf[i]==0x20/*space*/)  
  14.     {  
  15.       break;  
  16.     }  
  17.       method[i]=buf[i];       
  18.     }  
  19.   return method;  
  20. }  


3.依据URL的文件请求读取文件数据

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. char * fetchFileName(const char * buf,int bufLen)  
  2. {  
  3.     char *fileName;  
  4.     int i=0, j=-1;  
  5.     if(!buf)  
  6.       {  
  7.         return NULL;  
  8.       }  
  9.     if(bufLen<=0)  
  10.       {  
  11.         return NULL;  
  12.       }  
  13.     fileName=(char *)malloc(FILE_NAME_LEN_MAX*sizeof(char));  
  14.     memset(fileName,'\0',FILE_NAME_LEN_MAX);  
  15.     //printf("\n---------------\n");  
  16.     for(i=0;i<bufLen;i++)  
  17.       {  
  18.         //printf("%c",buf[i]);  
  19.         if(buf[i]=='/')  
  20.           {  
  21.         j=0;  
  22.         continue;  
  23.           }  
  24.         if(j<0)  
  25.           {  
  26.         continue;  
  27.           }   
  28.         if(buf[i]==0x20)  
  29.           {  
  30.         break;  
  31.           }  
  32.         fileName[j]=buf[i];  
  33.         j++;              
  34.       }  
  35.     //printf("\n---------------\n");  
  36.     return fileName;  
  37. }  
  38.   
  39. char * readFileBytes(const char * fileName)  
  40. {  
  41.   int contentLen=0;  
  42.   char *content;  
  43.   if(!fileName)  
  44.     {  
  45.       return NULL;  
  46.     }  
  47.     
  48.   FILE *f=fopen(fileName,"r");  
  49.   if(!f)  
  50.   {  
  51.     return NULL;  
  52.   }   
  53.   fseek(f, 0,SEEK_END);  
  54.   contentLen=ftell(f);  
  55.   content=(char *)malloc(contentLen*sizeof(char));  
  56.   memset(content,'\0',contentLen);  
  57.   fseek(f,0,SEEK_SET);  
  58.   fread(content,1,contentLen,f);  
  59.   fclose(f);  
  60.   return content;  
  61. }  
4.响应文件请求

注意:最关键的就是构建HTTP的头

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void response(int connfd,char *responseContent,int responseContentLength,char *responseCode,char *contentType)  
  2. {  
  3.   char responseHeader [RESPONSE_HEADER_LENGTH_MAX];  
  4.   int headerLen=0;  
  5.   int offset=0;  
  6.   memset(responseHeader,'\0',RESPONSE_HEADER_LENGTH_MAX);  
  7. //HTTP头构建开始  
  8.   //HTTP  
  9.   strcpy(responseHeader+offset,"HTTP/1.1 ");  
  10.   offset+=strlen("HTTP/1.1 ");  
  11.   strcpy(responseHeader+offset,responseCode);  
  12.   offset+=strlen(responseCode);  
  13.   strcpy(responseHeader+offset,"\r\n");  
  14.   offset+=strlen("\r\n");  
  15.   
  16.   //Server  
  17.   strcpy(responseHeader+offset, "Server: My Web Server\r\n");  
  18.   offset+=strlen("Server: My Web Server\r\n");  
  19.   
  20.   //Content length  
  21.   strcpy(responseHeader+offset,"Content-Length: ");  
  22.   offset+=strlen("Content-Length: ");  
  23.   printf("content length=%d\n",responseContentLength);  
  24.   //strcpy(responseHeader+offset,(const char*)&responseContentLength);  
  25.   sprintf(responseHeader+offset,"%d",responseContentLength);  
  26.   offset+=sizeof(int);   
  27.   strcpy(responseHeader+offset,"\r\n");  
  28.   offset+=strlen("\r\n");  
  29.   
  30.   //Connection  
  31.   strcpy(responseHeader+offset,"Connection: Keep-Alive\r\n");  
  32.   offset+=strlen("Connection: Keep-Alive\r\n");  
  33.   
  34.   //Content type  
  35.   strcpy(responseHeader+offset,"Content-Type: ");  
  36.   offset+=strlen("Content-Type: ");  
  37.   strcpy(responseHeader+offset,contentType);  
  38.   offset+=strlen(contentType);  
  39.   strcpy(responseHeader+offset,"\r\n\r\n");  
  40.   offset+=strlen("\r\n\r\n");  
  41.   headerLen=offset;  
  42. //HTTP头构建结束   
  43.   //printf("Response Header:%s\n",responseHeader);  
  44.   
  45.   write(connfd,responseHeader,headerLen);//发送HTTP头  
  46.   
  47.   write(connfd,responseContent,responseContentLength);//发送响应数据  
  48. }  
5.分析XHR的FormData

(1)XHR的POST请求:POST请求的数据是以FormData的形式发送的,在服务端会收到相应的数据,下面是具体的分析代码。

1)分析FormData的分界线(boundary)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. char * fetchBoundary(const char * buf,int bufLen)  
  2. {  
  3.   char *boundaryBegin;  
  4.   char *boundaryTemp;  
  5.   char *boundary;  
  6.   const char boundaryKey[]="boundary=";  
  7.   int i;  
  8.   
  9.   if(!buf)  
  10.     {  
  11.       return NULL;  
  12.     }  
  13.   if(!strstr(buf,"multipart/form-data"))  
  14.     {  
  15.       return NULL;  
  16.     }  
  17.   boundaryBegin=strstr(buf,boundaryKey);  
  18.   if(!boundaryBegin)  
  19.     {  
  20.       return NULL;  
  21.     }  
  22.    i=0;  
  23.    //printf("###########################\n");   
  24.    boundaryTemp=(char *)malloc(BOUNDARY_LEN_MAX);  
  25.    memset(boundaryTemp,'\0',BOUNDARY_LEN_MAX);  
  26.    boundaryBegin+=strlen(boundaryKey);//move pointer.  
  27.    while(1)  
  28.      {  
  29.        boundaryTemp[i]=boundaryBegin[i];  
  30.        if(boundaryBegin[i]==0x0A)  
  31.      {  
  32.        break;  
  33.      }  
  34.        i++;  
  35.      }  
  36.    boundary=(char *)malloc(i);  
  37.    strcpy(boundary,boundaryTemp);  
  38.    //printf("boundary:%s\n",boundary);  
  39.    //printf("###########################\n");  
  40.    return boundary;  
  41. }  
2)分析FormData的具体数据

注:这里FormData的数据是以链表的形式储存的,FormData的结构见前面的代码。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. struct FormData * fetchFormData(const char * buf,const char *boundary)  
  2. {  
  3.   char * begin;  
  4.   char * end;  
  5.   char * formData;  
  6.   char line[VALUE_LEN_MAX];  
  7.   char * bufTemp;  
  8.   char * temp;  
  9.   char * fromData;  
  10.   char  split[]={0x0D,0x0A};  
  11.   char keyFlag[]="Content-Disposition: form-data; name=";  
  12.   int i,j,n,boundaryLen,bufLen;  
  13.   struct FormData *head,*current,*next;  
  14.   
  15.   if(!buf)  
  16.     {  
  17.       return;  
  18.     }  
  19.   
  20.   if(!boundary)  
  21.     {  
  22.       return;  
  23.     }  
  24.   printf("****************Form Data**************************\n");  
  25.   
  26.   boundaryLen=strlen(boundary);  
  27.   begin=(char *)malloc(boundaryLen+2+1);//2 is prefix "--"  
  28.   memset(begin,'-',boundaryLen+2);//begin boundary prefix "--"  
  29.   memcpy(begin+2,boundary,boundaryLen);  
  30.   
  31.   
  32.   end=(char *)malloc(boundaryLen+4+1);//4 is prefix "--" and suffix "--"  
  33.   memset(end,'-',boundaryLen+4);  
  34.   memcpy(end+2,boundary,boundaryLen);  
  35.   
  36.   
  37.   bufLen=strlen(buf);  
  38.   bufTemp=(char *)malloc(bufLen*sizeof(char));  
  39.   memset(bufTemp,0x0,bufLen);  
  40.   memcpy(bufTemp,buf,bufLen);  
  41.   
  42.   formData=strstr(bufTemp,begin);  
  43.   
  44.   i=0;  
  45.   n=strlen(formData);  
  46.   memset(line,0,VALUE_LEN_MAX);  
  47.   head=(struct FormData *)malloc(sizeof(struct FormData));  
  48.   head->Next=NULL;  
  49.   current=head;  
  50.   next=NULL;  
  51.   for(i=0,j=0;i<n;i++)  
  52.     {  
  53.       if(formData[i]!=0x0A&&formData[i]!=0x0D)//Not new line.  
  54.     {       
  55.        line[j++]=formData[i];  
  56.        continue;  
  57.     }  
  58.        j=0;  
  59.       if(strlen(line)<=0)  
  60.        {       
  61.      memset(line,0,VALUE_LEN_MAX);   
  62.        continue;  
  63.        }  
  64.       if(strstr(line,end))  
  65.     {  
  66.       break;  
  67.     }  
  68.       //printf("line:%s\n",line);    
  69.       if(*line==*begin)  
  70.     {  
  71.       next=(struct FormData*)malloc(sizeof(struct FormData));     
  72.       next->Next=NULL;     
  73.       current->Next=next;  
  74.       memset(line,0,VALUE_LEN_MAX);  
  75.       continue;  
  76.     }  
  77.       temp=strstr(line,keyFlag);  
  78.       if(temp)  
  79.     {  
  80.       strncpy(current->Key,temp+strlen(keyFlag)+1,strlen(line)-strlen(keyFlag)-2);//kick out quote of key.  
  81.     }  
  82.       else  
  83.     {  
  84.       strcpy(current->Value,line);  
  85.       current=next;  
  86.     }     
  87.     memset(line,0,VALUE_LEN_MAX);  
  88.     }  
  89.   
  90.   current=head;  
  91.   while(current!=NULL)  
  92.     {  
  93.       if(strlen(current->Key)>0)  
  94.     {  
  95.       printf("Name:%s  Data:%s\n",current->Key,current->Value);  
  96.     }  
  97.       current=current->Next;  
  98.     }  
  99.   printf("*********************************************\n");  
  100.   return head;  
  101. }  

2.XHR的GET请求:GET的请求的数据是含在URL中的,所以FormData需要从URL中分析得到。

注:对于XHR的GET请求,如果也以FormData的形式发送(即:xhr.open("GET",url,true);xhr.send(formData);),那么在服务端没有办法直接在服务端获取到数据。原因可能是GET请求的数据是以URL的形式来发出的,但在服务端却没法收到这一数据。不过,还是有一个变通的方法。既然GET请求是以URL形式发出请求的,那我何不直接构建成像GET请求形式的URL,再以XHR的形式发送呢?结果证明是可行的,效果图见前面。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int  hasFormDataInUrl(const char * buf,int bufLen)  
  2. {  
  3.   int i;  
  4.   if(!buf)  
  5.     {  
  6.       return 0;  
  7.     }  
  8.   printf("===========Check form data in url===============\n");  
  9.   for(i=0;i<bufLen;i++)  
  10.     {  
  11.       if(buf[i]==0x0D||buf[i]==0x0A)//Only check first line.  
  12.     {  
  13.       break;  
  14.     }  
  15.       if(buf[i]=='?')  
  16.     {  
  17.       return 1;  
  18.     }  
  19.     }  
  20.   printf("=================================================\n");  
  21.   return 0;  
  22. }  
  23. struct FormData * fetchFormDataInUrl(const char * buf)  
  24. {  
  25.   struct FormData *head,*current,*next;  
  26.   int i,keyIndex,valueIndex;  
  27.   if(!buf)  
  28.     {  
  29.       return NULL;  
  30.     }  
  31.   head=(struct FormData *)malloc(sizeof(struct FormData));  
  32.   head->Next=NULL;  
  33.   current=head;  
  34.   next=NULL;  
  35.   printf("****************Form Data**************************\n");  
  36.   for(i=0,keyIndex=-1,valueIndex=-1;;i++)  
  37.     {  
  38.       if(buf[i]==0x0D||buf[i]==0x0A)//Data is in first line.  
  39.     {  
  40.       break;  
  41.     }  
  42.       if(buf[i]=='?'||buf[i]=='&')  
  43.     {     
  44.       keyIndex=0;  
  45.       valueIndex=-1;  
  46.       next=(struct FormData*)malloc(sizeof(struct FormData));     
  47.       next->Next=NULL;     
  48.       current->Next=next;  
  49.       if(buf[i]=='&')  
  50.         {  
  51.           current=next;  
  52.         }  
  53.       continue;  
  54.     }  
  55.       if(buf[i]=='=')  
  56.     {  
  57.       keyIndex=-1;  
  58.       valueIndex=0;  
  59.       continue;  
  60.     }  
  61.       if(keyIndex>=0)  
  62.     {  
  63.       current->Key[keyIndex++]=buf[i];  
  64.     }  
  65.       if(valueIndex>=0)  
  66.     {  
  67.       current->Value[valueIndex++]=buf[i];  
  68.     }  
  69.     }  
  70.   current=head;  
  71.   while(current!=NULL)  
  72.     {  
  73.       if(strlen(current->Key)>0)  
  74.     {  
  75.       printf("Name:%s  Data:%s\n",current->Key,current->Value);  
  76.     }  
  77.       current=current->Next;  
  78.     }  
  79.   printf("*********************************************\n");  
  80.   return head;  
  81. }  

6.响应XHR的请求

注:在响应请求时,除了将收到的数据回馈回去之外,还回馈了服务端的时间。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void responseFormData(int connfd,struct FormData * head,const char *method)  
  2. {  
  3.   time_t current;  
  4.   struct tm *timeinfo;     
  5.   char backData[BACK_LEN_MAX];  
  6.   char sectionFlag[]="\r\n";  
  7.   int n;  
  8.   if(!head)  
  9.     {  
  10.       return;  
  11.     };  
  12.   memset(backData,0, BACK_LEN_MAX);  
  13.   sprintf(backData,"Method:%s%s",method,sectionFlag);  
  14.   n=strlen("Method")+strlen(method)+strlen(sectionFlag);  
  15.   while(head!=NULL)  
  16.     {  
  17.       if(strlen(head->Key)>0)  
  18.     {  
  19.       sprintf(backData+n,"%s:%s%s",head->Key,head->Value,sectionFlag);  
  20.       n+=strlen(head->Key)+strlen(head->Value)+strlen(sectionFlag);  
  21.     }  
  22.       head=head->Next;  
  23.     }  
  24.   time(&current);  
  25.   timeinfo = (struct tm *)localtime(&current);  
  26.   sprintf(backData+n,"Server time:%s%s",asctime(timeinfo),sectionFlag);  
  27.   response(connfd,backData,strlen(backData),"200 OK","text/html");  
  28. }  
  29.   
  30. void handleFormData(int connfd,const char * buf,const char * boundary,const int isFormDataInUrl/*0:not.1:is*/)  
  31. {  
  32.   struct FormData * head;  
  33.   char *method;  
  34.   if(isFormDataInUrl)  
  35.     {  
  36.       head=fetchFormDataInUrl(buf);  
  37.     }  
  38.   else  
  39.     {  
  40.       head=fetchFormData(buf,boundary);  
  41.     }  
  42.   method=fetchMethod(buf);  
  43.   responseFormData(connfd,head,method);  
  44. }  

附上XHR的WEB实现

xhr.html

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <html>  
  2. <head>  
  3.     <title>Async request test</title>  
  4.     <script type="text/javascript" src="xhr.js"></script>  
  5.     <script type="text/javascript">  
  6.         function Request() {  
  7.             var url = document.getElementById("url").value;  
  8.             var data1 = document.getElementById("data1").value;  
  9.                     var data2 = document.getElementById("data2").value;    
  10.                     var method=document.getElementById("method").value;    
  11.             var formData =null;  
  12.             if(method==="POST")  
  13.             {  
  14.                 formData=new FormData();  
  15.                 formData.append("Data1", data1);  
  16.                         formData.append("Data2", data2);  
  17.                     }  
  18.                     else if(method==="GET")  
  19.                     {  
  20.                         url+="/?Data1="+data1+"&Data2="+data2;    
  21.                     }  
  22.                     else  
  23.                     {  
  24.                         alert(method+" not support");         
  25.                         return;  
  26.                     }  
  27.             Send(url, function (e) {  
  28.                 alert(e);  
  29.             },method,formData);  
  30.         }  
  31.     </script>  
  32. </head>  
  33. <body>  
  34.     <div>  
  35.         <a> URL:</a><input id="url" type="text" value="http://192.168.80.131:16800" style="width:200px;"/>  
  36.     </div>  
  37.     <div>  
  38.         <a>Data1:</a><input id="data1" type="text" value="ABCDEFG" style="width:200px;"/>  
  39.     </div>  
  40.     <div>  
  41.                 <a>Data2:</a><input id="data2" type="text" value="1234567" style="width:200px;"/>  
  42.     </div>   
  43.     <div>  
  44.                 <a>Method:</a><input id="method" type="text" value="GET" style="width:200px;"/>  
  45.     </div>   
  46.     <div>  
  47.         <input type="button" value="XHR" onclick="Request()" />  
  48.     </div>  
  49. </body>  
  50. </html>  

xhr.js

[javascript]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. function Send(url, callback,method,formData) {  
  2.     var xhr = new XMLHttpRequest();  
  3.     xhr.onreadystatechange = function () {  
  4.         if (xhr.readyState == 4) {  
  5.             if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) //200:Success.304:Tell browser to read cache.  
  6.             {  
  7.                 if (callback === undefined || callback === null) {  
  8.                     return;  
  9.                 }  
  10.                 callback(xhr.responseText);  
  11.             }  
  12.             else {  
  13.                 alert(xhr.responseText);  
  14.             }  
  15.         }  
  16.     }   
  17.     xhr.open(method, url, true);  
  18.     if (formData===undefined) {  
  19.         formData = null;  
  20.     }  
  21.     if(method==="GET")  
  22.     {  
  23.         xhr.send(null);   
  24.     }  
  25.     else  
  26.     {  
  27.             xhr.send(formData);     
  28.     }  
  29. }  


以上是WEB服务及响应XHR请求的简单实现,实现过程中的代码有很多需要改善的地方,请各路大牛多多指点。

源码可以此处下载http://download.youkuaiyun.com/detail/xxdddail/6889831

转载请注明出处http://blog.youkuaiyun.com/xxdddail/article/details/18841325





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值