web服务器程序
这篇文章是基于Linux系统上,介绍的Web服务器简单的编程和使用。
一、web服务器概述
当浏览器(客户端)运行时 webserver 服务器就会收到如下格式报文请求:
GET /index.html HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: 192.168.139.128:8000
Connection: Keep-Alive
该报文表示 : 浏览器(客户端)希望 webserver 给它发送名为 /html/index.html 的网页文件。webserver 服务器就要提取报文
中的网页文件路径 /html/index.html ,并在webserver 指定的目录下按提取到的路径 /html/index.html 打开网页文件,如果网页文
件打开成功,读取文件的数据,在 webserver 服务器传送网页文件数据前给浏览器(客户端)发送一条 “ 请求成功 ” 报文,
表示 webserver 服务器已经在找到浏览器(客户端)所要的网页文件。然后再不停地传送网页文件数据直到传输完毕。如果网页
文件失败 , 则 webserver 服务器向浏览器 ( 客户端 ) 发送一条 “ 请求失败 ” 报文 ,然后关闭 accpet 返回的套接字。
请求成功报文格式:
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>";
二、网页index.html程序
在家目录下创建html文件夹:mkdir html
在html文件加下创建index.html文件:vi index.html
<html>
<head>
<title>html</title>
<meta http-equiv="content-type" content="text/html; charset=gb2312" />
<meta http-equiv="refresh" content="5;url=http://blog.csdn.net/hanbo622/">
<meta name="keywords" content="jump">
</head>
<body>
5秒后将去<韩搏的专栏>敬请等待!
</body>
</html>
三、webserver程序
在家目录下创建webserver.c文件:vi webserver.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
/************************************************************************
函数功能: 通过线程创建webserver
函数参数: arg 已连接套接字
函数返回: 无
************************************************************************/
void * client_process(void *arg)
{
int connfd = (int)arg;
int fd = 0;
int len = 0;
char recv_buf[1024] = "";
char file_buf[1024] = "";
char filename[50] = "html/";
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>";
recv(connfd, recv_buf, sizeof(recv_buf), 0); //接收请求
sscanf(recv_buf, "GET /%[^ ]", (filename + 5)); //获取文件名
if(filename[5] == 0) //判断如果没有传入文件名,则使用默认的文件
{
strcpy(filename, "html/index.html");
}
fd = open(filename, O_RDONLY);
if(fd < 0)
{
perror("open");
send(connfd, err, strlen(err), 0); //发送失败的报文头
close(connfd);
return NULL;
}
send(connfd, head, strlen(head), 0); //发送成功的报文头
while((len = read(fd, file_buf, sizeof(file_buf))) > 0) //循环读取并发送文件
{
send(connfd, file_buf, len, 0);
}
close(fd);
close(connfd);
return NULL;
}
int main(int argc, char *argv[])
{
unsigned short port = 8000;
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror("socket");
exit(-1);
}
struct sockaddr_in my_addr;
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));
if(err_log != 0)
{
perror("bind");
close(sockfd);
exit(-1);
}
err_log = listen(sockfd, 10);
if(err_log != 0)
{
perror("listen");
close(sockfd);
exit(-1);
}
while(1)
{
char cli_ip[INET_ADDRSTRLEN] = "";
struct sockaddr_in client_addr;
socklen_t cliaddr_len = sizeof(client_addr);
int connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);
if(connfd < 0)
{
perror("accept");
continue;
}
else
{
pthread_t tid;
inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);
printf("connected form:IP=%s, PORT=%d\n\r", cli_ip,ntohs(client_addr.sin_port));
/*为每一个请求创建一个服务线程*/
pthread_create(&tid, NULL, client_process, (void *)connfd);
/*分离线程,当线程结束时,系统会自动释放其资源*/
pthread_detach(tid);
}
}
close(sockfd); //关闭监听套接字
return 0;
}
注意:最后编译生成的可执行文件必须和html文件夹在同一目录下运行。
四、使用浏览器访问
在浏览器地址栏输入:http://192.168.139.128:8000(此IP为运行webserver系统IP,端口号为webserver程序设置的端口号)
更多推荐
所有评论(0)