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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值