目录
前言
1 实验题目
2 实验目的
3 实验内容
3.1 步骤
3.2 关键代码
3.2.1 利用Stringsplit函数将浏览器发送的请求头信息进行解析
3.2.2 利用getRfcTime函数将本地时间转换为浏览器需要的RFC时间格式
3.2.3 利用getHeader函数根据Stringsplit函数解析得到的请求信息生成成功响应头或失败响应头
3.2.4 利用getContent函数根据Stringsplit函数解析得到的请求路径生成相应的响应数据
4 实验结果与分析
5 代码
本实验为计算机网络课程设计内容,基本上所有代码都是根据指导书给的附录写出来的。有些实验需要实现图形界面,但是出于期末考试压力,我所有实验均是在控制台输入输出的,没有花额外时间去学习qt了,有精力的同学可以自学一下qt实现简单的图形界面。同时,该博客内容为部分报告内容,仅为大家提供参考,请勿直接抄袭。另外,本次实验所用平台是dev c++5.11
实验九 简单 Web Server 程序的设计与实现
Web 服务是 Internet 最方便与受用户欢迎的服务类型,它的影响力也远远超出了专业技术范畴,已广泛应用于电子商务、远程教育、远程医疗与信息服务等领域,并且有继续扩大的趋势。目前很多的 Internet 应用都是基于 Web 技术的,因此掌握 Web 环境的软件编程技术对软件人员是至关重要的。
编写简单的 Web Server 有助于读者了解 Web Server 的工作流程,掌握超文本传送协议( HTTP)基本原理,掌握 Windows 环境中用 socket 实现 C/S 结构程序的编程方法。
(1)创建套接字并进行初始化。
(2)绑定套接字到本地端口,用于监听来自客户端的连接。
(3)循环接受客户端连接,接收并解析HTTP请求。
(4)根据请求生成HTTP响应,发送给客户端。
void Stringsplit(string str, const char split,vector& res) {
/*
GET / HTTP/1.1
Host: 192.168.142.119:8000
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
*/
istringstream iss(str); // 输入流
string token; // 接收缓冲区
getline(iss, token,'\n');
cout<<"token:"<
char * getRfcTime() {
time_t timep;
struct tm *p;
static char timeBuf[30];
time(&timep); //获取从1970至今过了多少秒,存入time_t类型的timep
p = localtime(&timep);//用localtime将秒数转化为struct tm结构体
sprintf(timeBuf,"%s, %d %s %d %02d:%02d:%02d GMT\r\n",
wday[p->tm_wday],p->tm_mday,month[p->tm_mon],1900 + p->tm_year,p->tm_hour, p->tm_min, p->tm_sec);
return timeBuf;
}
string getHeader(bool state) {
/*
HTTP/1.1 200 OK
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/html;charset=ISO-8859-1
Content-Length:
*/
string header = "";
if(state) {
header = header + "HTTP/1.1 200 OK" + "\r\n";
header = header + "Date: ";
//Sat, 31 Dec 2005 23:59:59 GMT
char *timeP = getRfcTime();
char timeBuf[30] = "\0";
strcpy(timeBuf,timeP);
header = header + + timeBuf;
header = header + "Content-Type: text/html;charset=UTF-8" + "\r\n";
header = header + "Content-Length: ";
} else if(state == false) {
header = header + "HTTP/1.1 404 Not Found" + "\r\n";
header = header + "Date: ";
char *timeP = getRfcTime();
char timeBuf[30] = "\0";
strcpy(timeBuf,timeP);
header = header + + timeBuf;
header = header + "Content-Type: text/html;charset=UTF-8" + "\r\n";
header = header + "Content-Length: ";
}
return header;
}
string getContent(vector res) {
string content="";
string header= "";
int sendCode;
if(res[1]=="/") {
res[1]="index.html";
} else {
res[1]=res[1].substr(1,res[1].size());
}
ifstream infile;
infile.open(res[1], ios::in);
if (!infile.is_open()) {
cout << "获取文件"<
(1)启动MyWebServer监听客户端请求。
图1.1 启动MyWebServer
(2)实验项目的同级和二级目录下的文件信息。
图1.2 项目的同级目录下的文件
图1.3 项目的二级目录下的文件
(3)打开浏览器,在请求路径栏只输入ip地址和端口号响应index.htm
图1.4 只输入ip地址和端口号
(4)请求其他的正确文件会响应相应的信息,例如请求hardwork.html、shiyan9.html、data.txt文件和/test/end.html文件。
图1.5 请求hardwork.html
图1.6 请求shiyan9.html文件中的信息
图1.7 请求data.txt文件
图1.8 请求/test/end.html文件
(5)请求不存在的目录文件显示404错误信息。
图1.9 404错误信息
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(lib,"ws2_32")
//#pragma comment ( lib , "Protocol.lib" )
using namespace std;
typedef long long LL;
const int maxn = 10010;
const char *wday[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
const char *month[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
string html =
"\n\
\n\
index.html \n\
\n\
\n\
This is index.html
\n\
你好
\n\
\n\
";
void Stringsplit(string str, const char split,vector& res) {
/*
GET / HTTP/1.1
Host: 192.168.142.119:8000
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
*/
istringstream iss(str); // 输入流
string token; // 接收缓冲区
getline(iss, token,'\n');
cout<<"token:"<tm_wday],p->tm_mday,month[p->tm_mon],1900 + p->tm_year,p->tm_hour, p->tm_min, p->tm_sec);
return timeBuf;
}
string getHeader(bool state) {
/*
HTTP/1.1 200 OK
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/html;charset=ISO-8859-1
Content-Length:
*/
string header = "";
if(state) {
header = header + "HTTP/1.1 200 OK" + "\r\n";
header = header + "Date: ";
//Sat, 31 Dec 2005 23:59:59 GMT
char *timeP = getRfcTime();
char timeBuf[30] = "\0";
strcpy(timeBuf,timeP);
header = header + + timeBuf;
header = header + "Content-Type: text/html;charset=UTF-8" + "\r\n";
header = header + "Content-Length: ";
} else if(state == false) {
header = header + "HTTP/1.1 404 Not Found" + "\r\n";
header = header + "Date: ";
char *timeP = getRfcTime();
char timeBuf[30] = "\0";
strcpy(timeBuf,timeP);
header = header + + timeBuf;
header = header + "Content-Type: text/html;charset=UTF-8" + "\r\n";
header = header + "Content-Length: ";
}
return header;
}
string getContent(vector res) {
string content="";
string header= "";
int sendCode;
if(res[1]=="/") {
res[1]="index.html";
} else {
res[1]=res[1].substr(1,res[1].size());
}
ifstream infile;
infile.open(res[1], ios::in);
if (!infile.is_open()) {
cout << "获取文件"<h_addr_list[0][0]&0x00ff),(p->h_addr_list[0][1]&0x00ff),
(p->h_addr_list[0][2]&0x00ff),(p->h_addr_list[0][3]&0x00ff),htons(addrSrv.sin_port));
cout<<"-------------------------------------------\n";
SOCKADDR_IN addrClient;
int len=sizeof(SOCKADDR);
int sendCode,recvCode;
char recvBuf[2048];
char sendBuf[2048];
vector v;
SOCKET tempSockConn;
string sendStr="";
while(1) {
cout<<"等待客户端连接\n";
SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);
cout<<"\nsockConn:"<