概述:
这个项目是一个用C语言实现的简易Web服务器,使用了套接字(sockets)和pthread。服务器能够处理基本的HTTP请求,提供静态HTML和图片文件。它采用多线程以同时处理多个客户端连接。
主要特点:
- HTTP服务器: 在指定的端口(这里是8080)监听传入的HTTP请求。
- 多线程: 利用pthread以同时处理多个客户端连接,提高服务器的响应性。
- 文件处理: 根据客户端请求,支持提供HTML和JPG文件。如果请求的文件类型不受支持,将默认提供index.html文件。
- 错误处理: 对套接字创建、绑定和监听进行基本的错误检查。
- 日志记录: 将相关信息(如请求的文件名和任何错误)输出到控制台进行调试。
使用方法:
- 使用C编译器编译程序(例如
gcc 文件名.c -o 服务器 -lpthread
)。 - 运行编译后的可执行文件。
- 通过打开Web浏览器并访问
http://localhost:8080
来访问服务器。
项目代码
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <netinet/in.h>
#include<fcntl.h>
#include<pthread.h>
using namespace std;
#define PORT 8080
void* fun(void* clint_fd)
{
int fd=*((int*)clint_fd);
char buff[1024]={0};
char respose[1024*1024],respose_head[1024];
int re=read(fd,buff,sizeof buff); //读取连接请求
//printf("%s\n",buff);
char name[100];
char* type= nullptr;
sscanf(buff,"GET /%s",name);
if(strstr(name,".html")) //html文件请求
{
type="text/html";
}else if(strstr(name,".jpg")) //jpg文件请求
{
type="image/jpg";
}else //若出现其他类型文件则直接返回主页面index.html
{
strcpy(name,"index.html");
type="text/html";
}
int file_fd=open(name,O_RDONLY);
if(file_fd==-1)
{
printf("filename:%s\n",name);
printf("file open error\n");
return nullptr;
}
sprintf(respose_head,"HTTP/1.1 200 OK\nContent-Type:%s\n\n",type); //响应头
write(fd,respose_head,strlen(respose_head));
while(read(file_fd,respose,(sizeof(respose)))>0) { //相应主体
write(fd, respose, sizeof respose);
}
if(strcmp(type,"text/html")==0)
{
printf("%s\n",respose);
}
close(fd);
close(file_fd);
}
int main()
{
int sever_fd= socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in sever_addr={0};
sever_addr.sin_family=AF_INET;
sever_addr.sin_addr.s_addr=INADDR_ANY;
sever_addr.sin_port= htons(PORT);
if(bind(sever_fd,(struct sockaddr*)&sever_addr, sizeof(sever_addr))==-1)
{
printf("bind error%m\n");
exit(-1);
}
if(listen(sever_fd,10)==-1)
{
printf("listen error%m\n");
exit(-2);
}
while(1)
{
struct sockaddr_in clint_addr={0};
int len=0;
int clint_fd= accept(sever_fd, (struct sockaddr*)&clint_addr, (socklen_t *)&len); //接收连接
pthread_t tid;
if(clint_fd==-1)
{
printf("clint_fd error clint_fd:%d\n",clint_fd);
break;
}
pthread_create(&tid,NULL,fun,&clint_fd); //创建线程,处理接受的连接
}
return 0;
}