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 檔案資料,并且在浏覽器渲染:

所有代碼如下:
#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);
}
}