Web服务器编程
Web编程
服务器应答格式:
服务器接收到浏览器的数据之后,需要判断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.1
char filename[N] = {0};
sscanf(buf, "GET /%s", filename); // sscanf()函数与空格结束,所以直接可以获取到文件名
// 截取文件名后判段一下是否是HTTP/1.1
if (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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· Qt个人项目总结 —— MySQL数据库查询与断言