Web编程
Web编程.c
服务器应答格式:
服务器接收到浏览器的数据之后,需要判断GET/后面跟的网页是否存在,如果存在则请求成功,发送指定的指令,并发送文件内容给浏览器,如果不存在,则发送请求失败的指令
请求成功:
"HTTP/1.1 200 OK\r\n " \
"Content-Type: text/html\r\n" \
"\r\n";
请求失败
"HTTP/1.1 400 OK\r\n " \"
"Content-Type: text/html\r\n" \
"\r\n" \
"<HTML><BOOY>File not found</BODY></HTML>"
案例
/*
# Web编程
# https://www.cnblogs.com/kencszqh
#
# File Name: Web_servicer.c
# Created : 2024-06-13
*/#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>#define PATH "./xxxwork/"
#define N 128
#define ERR_LOG(errmsg) \do \{ \perror(errmsg); \exit(1); \} while (0)void *pthread_func(void *arg)
{int acceptfd = *(int *)arg;char buf[N] = {0};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><h1>404 Not Found</h1></body></html>";// 接收浏览器通过HTTP协议发送的数据包if (recv(acceptfd, buf, N, 0) < 0){ERR_LOG("recv");}printf("%s\n", buf);// GET /index.html HTTP/1.1char filename[N] = {0};sscanf(buf, "GET /%s", filename); // sscanf()函数与空格结束,所以直接可以获取到文件名// 截取文件名后判段一下是否是HTTP/1.1if (strncmp(filename, "HTTP/1.1", strlen("http/1.1")) == 0){strcpy(filename, "index.html");}printf("filename:%s\n", filename);char path[N] = "PATH";// 通过解析出来的网页文件名,查找本地中有没有这个文件int fd;if ((fd = open(path, O_RDONLY)) < 0){// 如果文件不存在,则发生不存在对应的指令if (errno == ENOENT){if (send(acceptfd, err, strlen(err), 0) < 0){ERR_LOG("send");}close(acceptfd);pthread_exit(NULL);}else{ERR_LOG("open");}}// 如果文件存在,则发送文件内容if (send(acceptfd, head, strlen(head), 0) < 0){ERR_LOG("send");}// 读取文件内容,并发送给浏览器ssize_t n;char text[1024] = {0};while ((n = read(fd, text, sizeof(text))) > 0){if (send(acceptfd, text, n, 0) < 0){ERR_LOG("send");}}
}int main(int argc, char const *argv[])
{if (argc != 3){fprintf(stderr, "Usage:%s [ip] [port]\n", argv[0]);exit(1);}int sockfd, acceptfd;struct sockaddr_in serveraddr, clientaddr;socklen_t addrlen = sizeof(serveraddr);// 1.创建套接字if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ERR_LOG("socket");}// 2.绑定serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(atoi(argv[2]));serveraddr.sin_addr.s_addr = inet_addr(argv[1]);if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0){ERR_LOG("bind");}// 3.监听if (listen(sockfd, 5) < 0){ERR_LOG("listen");}// 4.接受客户端连接while (1){if ((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen)) < 0){ERR_LOG("accept");}printf("client ip:%s,port:%d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));pthread_t thread;if (pthread_create(&thread, NULL, pthread_func, &acceptfd) != 0){ERR_LOG("pthread_create");}pthread_detach(thread);}return 0;
}