简易HTTP 服务器

//=============================================================
// 文件名称:web.c
// 功能描述:HTTP Server
// 维护记录:2011-05-04 V1.0
// 维护成员: wenhao
//=============================================================
#include <stdio.h>
#include
<stdlib.h>
#include
<string.h> // bzero
#include <unistd.h>
#include
<sys/socket.h>
#include
<netinet/in.h>
#include
<arpa/inet.h> // inet_ntop
#include <pthread.h>
#include
<sys/stat.h>
#include
<sys/types.h>
#include
<fcntl.h>


//=============================================================
// 语法格式: void main(void)
// 实现功能: 主函数,建立一个HTTP Server
// 入口参数: 无
// 出口参数: 无
//=============================================================
int main(int argc, char *argv[])
{
int sockfd; // 套接字
pid_t pid; //进程ID
struct sockaddr_in servAddr; // 服务器地址结构体
struct sockaddr_in cliAddr; // 用于保存客户端地址
char cliIP[INET_ADDRSTRLEN]; // 用于保存客户端IP地址
unsigned short port = 80; // 监听端口
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>";

size_t cliAddrLen
= sizeof(cliAddr); //计算客户端的地址大小

if(argc > 1) // 由参数接收端口
{
port
= atoi(argv[1]);
}
printf(
"TCP Server Started at port %d!\n", port);
sockfd
= socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字
if(sockfd < 0)
{
perror(
"Invalid socket");
exit(
1);
}
memset(
&servAddr,0,sizeof(servAddr));// 初始化服务器地址
servAddr.sin_family = AF_INET;
servAddr.sin_port
= htons(port);
servAddr.sin_addr.s_addr
= htonl(INADDR_ANY);
printf(
"Binding server to port %d\n", port);
if(bind(sockfd, (struct sockaddr*)&servAddr, sizeof(struct sockaddr)) != 0) //bind绑定套接字
{
close(sockfd);
perror(
"binding err!");
exit(
1);
}
if(listen(sockfd, 1) != 0)//listen监听套接字
{
close(sockfd);
perror(
"listen err!");
exit(
1);
}
printf(
"waiting client...\n");

while(1)
{
int connfd = accept(sockfd, (struct sockaddr*)&cliAddr, &cliAddrLen);//等待服务器访问
printf("the connfd = *%d*\n",connfd);
inet_ntop(AF_INET,
&cliAddr.sin_addr.s_addr, cliIP, INET_ADDRSTRLEN);
printf(
"client ip = %s\n", cliIP);
pid
= fork(); //创建进程
if(pid == 0)
{
close(sockfd);
//子进程中关闭主套接字
char recvbuf[1024]=""; // 接收缓冲区
char filename[100];
int openfd;
char filebuf[1024];
read(connfd,recvbuf,
1024);//从套接字中读取浏览器发送过来的数据.
sscanf(recvbuf,"GET /%[^ ]",filename); //获取要浏览器请求的文件
printf("filename = *%s*\n",filename);
openfd
= open(filename,O_RDONLY); //打开浏览器请求的文件
if(openfd == -1)
{
printf(
"the file open error!\n");
write(connfd,err,strlen(err));
//文件打开失败发送错误提示
}
else
{
printf(
"the file open successful!\n");
//注意这里是用strlen(head),而不是sizeof(),用sizeof将会导致图片打不开
send(connfd,head,strlen(head),0); //向浏览器发送请求OK的消息
int readflag = 0;
//将打开的文件中的数据依次的发送给浏览器
while((readflag=read(openfd,filebuf,sizeof(filebuf))) > 0)
{
printf(
"readflag = *%d*\n",readflag);
send(connfd,filebuf,readflag,
0);//这里的发送数据大小为readflag,注意
}
}
close(connfd);
//本次请求结束后关闭套接字
exit(0);//退出进程
}
else
{
close(connfd);
//主进程要关闭子进程中用到的套接字,不然再次有请求时,会导致网页始终打不开.
}
}
close(sockfd);
return 0;
}
原文地址:https://www.cnblogs.com/hnrainll/p/2036725.html