天天看点

C 语言实现一个简单的 web 服务器(二)

2.6 请求处理层编写

得到请求后开始编写处理层。继续接着代码往下写没有层级,编写一个函数名为 req,该函数接收请求信息与一个建立好的连接为参数:

void req(char* buf, int access_socket)

{

}

然后先在 while 循环中传递需要的值:

req(buf, access_skt);

接着开始编写 req 函数,首先在 req 函数中标记当前目录下:

char arguments[BUFSIZ];  
strcpy(arguments, "./");
随后分离出请求与参数:
char command[BUFSIZ];     
sscanf(request, "%s%s", command, arguments+2);
接着我们标记一些头元素:
char* extension = "text/html";   
char* content_type = "text/plain";     
char* body_length = "Content-Length: ";
接着获取请求参数,若获取 index.html,就获取当前路径下的该文件:
FILE* rfile= fopen(arguments, "rb");
获取文件后表示请求 ok,我们先返回一个 200 状态:
char* head = "HTTP/1.1 200 OK\r\n";    
int len; 
char ctype[30] = "Content-type:text/html\r\n";   
len = strlen(head);      

接着编写一个发送函数 send_:

int send_(int s, char *buf, int *len) 
{
 int total;          
 int bytesleft;                                
 int n;
 total=0;
 bytesleft=*len;
 while(total < *len) 
 {
  n = send(s, buf+total, bytesleft, 0);
  if (n == -1) 
  {
   break;
  }
  total += n;
  bytesleft -= n;
 }
 *len = total;          
 return n==-1?-1:0;         
}      

send 函数功能并不难在此不再赘述,就是一个遍历发送的逻辑。随后发送 http 响应与文件类型:

send_(send_to, head, &len);

len = strlen(ctype);

send_(send_to, ctype, &len);

随后获得请求文件的描述,需要添加头文件#include <sys/stat.h>使用fstat,且向已连接的通信发生必要的信息 :

//获取文件描述
struct stat statbuf;
char read_buf[1024];       
char length_buf[20];
fstat(fileno(rfile), &statbuf);
itoa( statbuf.st_size, length_buf, 10 );
send(client_sock, body_length, strlen(body_length), 0);
send(client_sock, length_buf, strlen(length_buf), 0);
send(client_sock, "\n", 1, 0);
send(client_sock, "\r\n", 2, 0);      

最后发送数据:

//·数据发送

char read_buf[1024]; 
len = fread(read_buf ,1 , statbuf.st_size, rfile);
if (send_(client_sock, read_buf, &len) == -1) { 
 printf("error!");   
}      

最后访问地址

http://127.0.0.1:8080/index.html

,得到当前目录下 index.html 文件数据,并且在浏览器渲染:

C 语言实现一个简单的 web 服务器(二)

所有代码如下:

#include <WinSock2.h>
#include<stdio.h> 
#include <sys/stat.h> 
 
int send_(int s, char *buf, int *len) {
 int total;          
 int bytesleft;                                
 int n;
 total=0;
 bytesleft=*len;
 while(total < *len) 
 {
  n = send(s, buf+total, bytesleft, 0);
  if (n == -1) 
  {
   break;
  }
  total += n;
  bytesleft -= n;
 }
 *len = total;          
 return n==-1?-1:0;         
}
 
void req(char* request, int client_sock) {   
 char arguments[BUFSIZ];  
 strcpy(arguments, "./");
 
 char command[BUFSIZ];     
 sscanf(request, "%s%s", command, arguments+2);
 
 char* extension = "text/html";   
 char* content_type = "text/plain";     
 char* body_length = "Content-Length: ";
 
 FILE* rfile= fopen(arguments, "rb");
 
 
 char* head = "HTTP/1.1 200 OK\r\n";    
 int len; 
 char ctype[30] = "Content-type:text/html\r\n";   
 len = strlen(head);
  
 send_(client_sock, head, &len);
 len = strlen(ctype);
 send_(client_sock, ctype, &len);
 
 
 struct stat statbuf;
       
 char length_buf[20];
 fstat(fileno(rfile), &statbuf);
 itoa( statbuf.st_size, length_buf, 10 );
 send(client_sock, body_length, strlen(body_length), 0);
 send(client_sock, length_buf, strlen(length_buf), 0);
 
 send(client_sock, "\n", 1, 0);
 send(client_sock, "\r\n", 2, 0);
 
 
 char read_buf[1024]; 
 len = fread(read_buf ,1 , statbuf.st_size, rfile);
 if (send_(client_sock, read_buf, &len) == -1) { 
  printf("error!");   
 }
 
 return;
}
 
 
int main(){
 WSADATA wsaData;
 if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
  exit(1);
 }
 
 int skt = socket(PF_INET, SOCK_STREAM, 0);
 if (skt == -1) {         
  return -1;
 }
 
 struct sockaddr_in server_addr;
 server_addr.sin_family = AF_INET;
 server_addr.sin_port = htons(8080);
 server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
 memset(&(server_addr.sin_zero), '\0', 8);
 
 if (bind(skt, (struct sockaddr *)&server_addr,sizeof(server_addr)) == -1) {       
  return -1; 
 } 
 
 if (listen(skt, 10) == -1 ) {    
  return -1;
 }
 
 while(1){
 
  printf("Listening ... ...\n");
  struct sockaddr_in c_skt; 
  int s_size=sizeof(struct   sockaddr_in);
  int access_skt = accept(skt, (struct sockaddr *)&c_skt, &s_size);
 
  char buf[1024];
  if (recv(access_skt, buf, 1024, 0) == -1) {
   exit(1);
  }
  
  req(buf, access_skt);
 } 
 
}

      

继续阅读