//
=============================================================
// 文件名称: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 ;
}
// 文件名称: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 ;
}