webserver通信过程
生活随笔
收集整理的這篇文章主要介紹了
webserver通信过程
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?
?
?簡單的http服務(wù)器
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <string.h> #include <pthread.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h>#define N 1024 #define ERR_LOG(errmsg) do{\perror(errmsg);\printf("%s - %s - %d\n", __FILE__, __func__, __LINE__);\exit(1);\}while(0)void *pthread_fun(void *arg) {int acceptfd = *(int *)arg;char buf[N] = "";char head[]="HTTP/1.1 200 OK\r\n" \"Content-Type: text/html\r\n" \"\r\n"; char err[]= "HTTP/1.1 404 Not Found\r\n" \"Content-Type: text/html\r\n" \"\r\n" \"<HTML><BODY>File not found</BODY></HTML>";//接收瀏覽器通過http協(xié)議發(fā)送的數(shù)據(jù)包if(recv(acceptfd, buf, N, 0) < 0){ERR_LOG("fail to recv");}printf("*****************************\n\n");printf("%s\n", buf);// int i;// for(i = 0; i < 200; i++)// {// printf("[%c] - %d\n", buf[i], buf[i]);// }printf("\n*****************************\n");//通過獲取的數(shù)據(jù)包中得到瀏覽器要訪問的網(wǎng)頁文件名//GET /about.html http/1.1char filename[128] = "";sscanf(buf, "GET /%s", filename); //sscanf函數(shù)與空格結(jié)束,所以直接可以獲取文件名if(strncmp(filename, "HTTP/1.1", strlen("http/1.1")) == 0){strcpy(filename, "about.html");}printf("filename = %s\n", filename);char path[128] = "./sqlite/";strcat(path, filename);//通過解析出來的網(wǎng)頁文件名,查找本地中有沒有這個(gè)文件int fd;if((fd = open(path, O_RDONLY)) < 0){//如果文件不存在,則發(fā)送不存在對(duì)應(yīng)的指令if(errno == ENOENT){if(send(acceptfd, err, strlen(err), 0) < 0){ERR_LOG("fail to send");}close(acceptfd);pthread_exit(NULL);}else{ERR_LOG("fail to open");}}//如果文件存在,先發(fā)送指令告知瀏覽器if(send(acceptfd, head, strlen(head), 0) < 0){ERR_LOG("fail to send");}//讀取網(wǎng)頁文件中的內(nèi)容并發(fā)送給瀏覽器ssize_t bytes;char text[1024] = "";while((bytes = read(fd, text, 1024)) > 0){if(send(acceptfd, text, bytes, 0) < 0){ERR_LOG("fail to send");}}pthread_exit(NULL); }int main(int argc, char const *argv[]) {if(argc < 3){fprintf(stderr, "Usage: %s <server_ip> <server_port>\n", argv[0]);exit(1);} int sockfd, acceptfd;struct sockaddr_in serveraddr, clientaddr;socklen_t addrlen = sizeof(serveraddr);//第一步:創(chuàng)建套接字if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ERR_LOG("fail to socket");}//將套接字設(shè)置為允許重復(fù)使用本機(jī)地址或者為設(shè)置為端口復(fù)用int on = 1;if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0){ERR_LOG("fail to setsockopt");}//第二步:填充服務(wù)器網(wǎng)絡(luò)信息結(jié)構(gòu)體serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr(argv[1]);serveraddr.sin_port = htons(atoi(argv[2]));//第三步:將套接字與服務(wù)器網(wǎng)絡(luò)信息結(jié)構(gòu)體綁定if(bind(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0){ERR_LOG("fail to bind");}//第四步:將套接字設(shè)置為被動(dòng)監(jiān)聽狀態(tài)if(listen(sockfd, 5) < 0){ERR_LOG("fail to listen");}while(1){//第五步:阻塞等待客戶端的連接請(qǐng)求if((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen)) < 0){ERR_LOG("fail to accept");}//打印客戶端的信息printf("%s -- %d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));//創(chuàng)建線程接收數(shù)據(jù)并處理數(shù)據(jù)pthread_t thread;if(pthread_create(&thread, NULL, pthread_fun, &acceptfd) != 0){ERR_LOG("fail to pthread_create");}pthread_detach(thread);}return 0; }?
總結(jié)
以上是生活随笔為你收集整理的webserver通信过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux下undefined refe
- 下一篇: 常考数据结构与算法:二叉树的之字形层序遍