基于UnixC的简单web服务器

本文介绍了一个简易Web服务器的实现过程,包括使用C语言编写HTTP请求解析、文件类型判断及响应生成等功能,通过fork()创建子进程处理每个客户端连接,展示了基本的服务器端编程技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

t_net.h和t_net.c的代码第十三天有,这里编译时连接打包好的动态库即可  

doit.h

#ifndef DO_IT_H_
#define DO_IT_H_
	#include<unistd.h>
	#include<ctype.h>
	#include<t_file.h>
	#include<sys/socket.h>
 	#include<sys/types.h>
	#include<netinet/in.h>
	#include<arpa/inet.h>
	typedef struct request{
  	char method[16];
  	char path[128];
  	char proto[16];
	}req_t;
	typedef struct response{
  	  int code;
   	 char *f_type;
	}res_t;
	
	void do_main(int fd);
	//int h_acc(int fd)


#endif

doit.c

#include"doit.h"
#include<string.h>
#include<t_stdio.h>
#include<t_net.h>
char *work_dir="/home/nan/SJW/webs/hhhlaugh";
//一定要考虑字符串的结尾符号\0
static void get_request(int fd,req_t *rq){
    char buf[1024]; 
    char path[128];
    //读取浏览器的请求头信息
    int r=read(fd,buf,1024);
    sscanf(buf,"%s %s %s\r\n",rq->method,rq->path,rq->proto);
    //处理/
	printf("%s\n",rq->method);
	printf("%s\n",rq->path);
	printf("%s\n",rq->proto);
    if(strcmp(rq->path,"/")==0)
        strcpy(rq->path,"/index.html");
    strcpy(path,work_dir);
    strcat(path,rq->path);
    strcpy(rq->path,path);
	printf("--->%s\n",rq->path);
    return;
}

//获取文件类型  content-type
static char *get_ftype(const char *file){
    if(strrchr(file,'.')==NULL)return "text/html";
    if(strcmp(strrchr(file,'.'),".png")==0)return "image/png";
    if(strcmp(strrchr(file,'.'),".jpg")==0)return "image/jpg";
    if(strcmp(strrchr(file,'.'),".gif")==0)return "image/gif";
    return "text/html";
}
static void orgn_response(const char *file,res_t *rs){
    //获取响应码
	//printf("12312432->%s\n",file);
  
	rs->code=access(file,R_OK)?404:200;
    //获取响应文件信息  text/html  image/jpg image/png
    rs->f_type=get_ftype(file);
	//if(rs->code==404)
		//printf("path--->%s\n",file);
}
//
static void res_b_200(int fd,req_t *rq,res_t *rs){
    char f_line[128];
    sprintf(f_line,"%s %d   ok\r\n",rq->proto,rs->code);
    char content[128];
    sprintf(content,"Content-Type: %s\r\n\r\n",rs->f_type);
    write(fd,f_line,strlen(f_line));
    write(fd,content,strlen(content));

    write(1,f_line,strlen(f_line));
    write(1,content,strlen(content));
	int s_fd=dup(1);
    dup2(fd,1);//将浏览器确定为标准输出
    if(rs->code==404){
        char path[128];
        strcpy(path,work_dir);
        strcat(path,"/error.html");
        strcpy(rq->path,path);
	//dup2(s_fd,1);
	printf("error path->%s\n",rq->path);
    }
	
    int a=execlp("cat","cat",rq->path,NULL);
	if(a==-1)
		perror("execlp");
    return;
}

void do_main(int fd){
   req_t req;
     res_t res;
   //获取客户端的请求信息
    get_request(fd,&req);
    printf("path:%s\n",req.path);
    //处理客户端的请求信息,组织响应信息
    orgn_response(req.path,&res);
    printf("code:%d\ttype:%s\n",res.code,res.f_type); 
    //响应客户端
    res_b_200(fd,&req,&res);
	//获取文件名
	//strchr
	//拼接路径
	//open 可读
	//读取文件内容
	//char buf[2048]={"HTTP/1.1 200 OK\r\n"};
//	strcat(buf,"");
	//发送
	/*char buf[1024];
	int r=read(fd,buf,1024);
	write(1,buf,r);*/
    return;
}

server.c

#include<t_stdio.h>
#include"doit.h"
#include<t_net.h>
#include<unistd.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<signal.h>
void handle(int n){
	wait(NULL);
	return;
}
int main(){
	signal(17,handle);
	int sfd=t_listen(AF_INET,SOCK_STREAM,3333,5);
	if(sfd==-1) return -1;
	
	
	while(1){//受理连接
		int cfd=h_accept(sfd);	
			if(cfd==-1) return -1;
		pid_t pid=fork();
			if(pid==-1) 
				E_MSG("fork",-1);
		if(pid==0){
			close(sfd);
			do_main(cfd);
			close(cfd);
			exit(0);
		}else{
		
		close(cfd);
		//waitpid(-1,NULL,WNOHANG);
		
	
		}
	}

	return 0;
}

使用浏览器    登录127.0.0.1:3333/index.html

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值