简易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 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值