webserver应该怎么去做?

来源:互联网 发布:药代动力学考研知乎 编辑:程序博客网 时间:2024/04/19 21:01



简单的webserver的实现:


二、 注意webserver是需要我们代码实现的,而客户端就是我们的浏览器。

三.webserver通信大致过程。
3.1:我们从浏览器(客服端)界面输入IP,端口,以及所要的文件路径和名称,一敲回
车,这时浏览器(客户端)就会把收到的命令请求发送到我们在Linux下编写webserver服务器.

3.2:作为webserver服务器这是就会收到浏览器(客户端)发来的
如下格式报文请求:
GET /html/index.html HTTP/1.1
Accept:image/gif.image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
Accept-Encoding:gzip,deflate
该报文表示:浏览器(客户端)希望webserver给它发送名为/html/index.html的网页文
件。
3.3:webserver 服务器就要提取报文中的网页文件路径/html/index.html , 并在
webserver指定的目录下按提取到的路径/html/index.html打开网页文件(在我们自己写的
webserver的服务器所指定的目录其实就是我们的可执行程序所在的目录,所以我们必须在
webserver运行前将我们的网页文件和可执行文件在同一目录下,当然可以通过程序来修改
路径)。
提取网页文件的具体方法:sscanf(buf, "GET /%[^ ]", filename);
3.4:webserver服务器提取到网页文件路径后,就要在去打开该网
页文件,以便把网页文件的数据发给浏览器(客户端)。
如果网页文件打开成功,则webserver服务器会在传送网页文件数据前给浏览器(客户
端)发送一条“请求成功”报文,表示webserver服务器已经在找到浏览器(客户端)所要的
网页文件。然后再不停地传送网页文件数据直到传输完毕。
“请求成功”报文格式:
char head[] = "HTTP/1.1 200 OK\r\n" \
"Content-Type: text/html\r\n" \
"\r\n";
如果网页文件失败,则webserver服务器向浏览器(客户端)发送一条“请求失败”报文,
然后关闭accpet返回的套接字。
“请求失败”报文格式:
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>";


代码参考:

*
 * =====================================================================================
 *
 *       Filename:  webserver_sample.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2015年03月10日 11时44分14秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Dr. moshui (no_water), 276908080@qq.com
 *   Organization:  
 *
 * =====================================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


int main(int argc, char *argv[])
{
int server_fd = 0, client_fd = 0;
struct sockaddr_in server_addr, client_addr;
socklen_t len = sizeof(client_addr);
unsigned short port = 8000;   //设置默认端口号


if(argc > 1)
{
port = atoi(argv[1]);//将参数2赋值给端口号变量
}

//套接字地址结构体变量清0
bzero(&client_addr, sizeof(client_addr));
bzero(&server_addr, sizeof(server_addr));

//服务器套接字地址变量赋值
server_addr.sin_family = AF_INET;   //IPV4族
server_addr.sin_port   = htons(port); //将端口号转换成网络字节序
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //本机IP地址

//创建TCP套接字
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if( server_fd < 0)
{
perror("socket error");
exit(-1);
}

//绑定TCP套接字
if( bind(server_fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) != 0)
{
perror("bind error");
close(server_fd);
exit(-1);
}

//监听
if( listen(server_fd, 10) != 0)
{
perror("listen error");
close(server_fd);
exit(-1);
}


printf("Listenning at port=%d\n",port);   //打印端口号信息
printf("Usage: http://172.20.223.16:%d/html/index.html\n",port);

while(1)
{
char cliaddrbuf[INET_ADDRSTRLEN] = "";  //存放客户端点分十进制IP地址

//等待客户端连接
client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &len);
printf("client_fd=%d\n",client_fd); //打印已连接套接字
if(client_fd > 0)
{
if(fork() == 0)  //创建进程并判断返回值
{
//子进程执行
int  fd = 0;
int  len = 0;
char buf[1024] = "";
char filename[50] = "";

//接收成功时返回的头部
char head[]="HTTP/1.1 200 OK\r\n"\
"Content-Type: text/html\r\n"\
"\r\n";

//将网络字节序转换成点分十进制形式存放在cliaddrbuf中
inet_ntop(AF_INET,&client_addr.sin_addr,cliaddrbuf,INET_ADDRSTRLEN);
printf("connected form %s\n\r", cliaddrbuf); //打印点分十进制形式的客户端IP地址
recv(client_fd,buf,sizeof(buf),0); //接收客户端发送的请求内容
sscanf(buf, "GET /%[^ ]", filename); //解析客户端发送请求字符串
printf("filename=*%s*\n",filename);

fd = open(filenamefilename, O_RDONLY); //以只读方式打开文件
if( fd < 0) //如果打开文件失败
{
//HTTP失败头部
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>";
perror("open error");
send(client_fd, err, strlen(err), 0);
close(client_fd);  //关闭已连接套接字
exit(0); //子进程退出
}
//打开文件成功后
send(client_fd, head, strlen(head), 0);//发送HTTP请求成功头部
while( (len = read(fd, buf, sizeof(buf))) > 0) //循环读取文件内容
{
send(client_fd, buf, len, 0);       //将读得的数据发送给客户端
}

close(fd);//成功后关闭文件
close(client_fd); //关闭已连接套接字
exit(0); //子进程退出
}
}

close(client_fd);//父进程关闭连接套接字
}
close(server_fd);
printf("exit main!\n");
return 0;
}








0 0
原创粉丝点击