欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

webserver通信过程

发布时间:2025/6/15 编程问答 29 豆豆
生活随笔 收集整理的这篇文章主要介绍了 webserver通信过程 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

 

 

 简单的http服务器

#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协议发送的数据包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");//通过获取的数据包中得到浏览器要访问的网页文件名//GET /about.html http/1.1char filename[128] = "";sscanf(buf, "GET /%s", filename); //sscanf函数与空格结束,所以直接可以获取文件名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);//通过解析出来的网页文件名,查找本地中有没有这个文件int fd;if((fd = open(path, O_RDONLY)) < 0){//如果文件不存在,则发送不存在对应的指令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");}}//如果文件存在,先发送指令告知浏览器if(send(acceptfd, head, strlen(head), 0) < 0){ERR_LOG("fail to send");}//读取网页文件中的内容并发送给浏览器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);//第一步:创建套接字if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ERR_LOG("fail to socket");}//将套接字设置为允许重复使用本机地址或者为设置为端口复用int on = 1;if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0){ERR_LOG("fail to setsockopt");}//第二步:填充服务器网络信息结构体serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr(argv[1]);serveraddr.sin_port = htons(atoi(argv[2]));//第三步:将套接字与服务器网络信息结构体绑定if(bind(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0){ERR_LOG("fail to bind");}//第四步:将套接字设置为被动监听状态if(listen(sockfd, 5) < 0){ERR_LOG("fail to listen");}while(1){//第五步:阻塞等待客户端的连接请求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));//创建线程接收数据并处理数据pthread_t thread;if(pthread_create(&thread, NULL, pthread_fun, &acceptfd) != 0){ERR_LOG("fail to pthread_create");}pthread_detach(thread);}return 0; }

 

总结

以上是生活随笔为你收集整理的webserver通信过程的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。