网页要与硬件打交道,通常的方式是使用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的形式监听服务端口。
/* server.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXLINE 1024
#define FILE_NAME_LEN_MAX 256
#define DEFEULT_SERVER_PORT 8000
#define RESPONSE_HEADER_LENGTH_MAX 1024
#define BOUNDARY_LEN_MAX 256
#define KEY_LEN_MAX 256
#define VALUE_LEN_MAX 1024
#define BACK_LEN_MAX 10240
#define FORM_DATA_LEN_MAX 10240
struct FormData
{
char Key[KEY_LEN_MAX];
char Value[VALUE_LEN_MAX];
struct FormData *Next;
};
char * fetchMethod(const char * buf);
int hasFormDataInUrl(const char * buf,int bufLen);
char * fetchFileName(const char * buf,int bufLen);
char * readFileBytes(const char * fileName);
char * fetchBoundary(const char * buf,int bufLen);
void handleFormData(int connfd,const char * buf,const char * boundary,const int isFormDataInUrl/*0:not.1:is*/);
struct FormData * fetchFormData(const char * buf,const char *boundary);
struct FormData * fetchFormDataInUrl(const char * buf);
void responseFormData(int connfd,struct FormData * head,const char *method);
void response(int connfd,char *responseContent,int responseContentLength,char *responseCode,char *contentType);
int main(int argc, char *argv[])
{
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddr_len;
int listenfd, connfd;
char buf[MAXLINE];
char *data;
char *responseContent;
char str[INET_ADDRSTRLEN];
char *method;
char *fileName;
char *boundary;
int i,n;
int port= DEFEULT_SERVER_PORT;
if(argc>1)
{
port=atoi(argv[1]);//Input port
}
if(port<=0||port>0xFFFF)
{
printf("Port(%d) is out of range(1-%d)\n",port,0xFFFF);
return;
}
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(listenfd, 20);
printf("Listen %d\nAccepting connections ...\n",port);
while (1)
{
cliaddr_len = sizeof(cliaddr);
connfd = accept(listenfd,
(struct sockaddr *)&cliaddr, &cliaddr_len);
n = read(connfd, buf, MAXLINE);
printf("---------------------\n");
printf("received from %s at PORT %d\n",
inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
ntohs(cliaddr.sin_port));
printf("read:%d\n%s\n",n,buf);
method=fetchMethod(buf