Web服务器实验3报告_web服务器实验3报告
Web服务器实验3报告由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“web服务器实验3报告”。
操作系统实验报告三
姓名:陈玉博
学号:2011011207
日期:2013-11-24
【实验内容】:设计一段内存结构,能够缓存一定数量的网页,在客户端访问时,首先从内存中查找是否存在客户端访问的网页内容,如果存在,则直接从内存中将相应的内容返回给客户端;如果不存在,则从磁盘中将网页内容读入到内存,并返回给客户端。【实验思路】:客户端连接之后,在线程的处理函数handle()函数中,从内存中查找相应的网页内容,发送至客户端。如果在内存中找不到,则通过调用store()函数从磁盘中读取该网页到内存,当内存中的网页个数大于100的时候,通过某种算法从内存中移除某个网页,然后重新存入新的网页。在主函数中,连接成功以后调用handle()函数,然后在handle()函数中,如果找不到请求的网页,则调用store()函数。【主要代码及注释】----main函数:
void main(int argc, _TCHAR* argv[]){ //声明处理函数,作为QueueUserWorkItem的一个参数
DWORD WINAPI handle(void *);//初始化WinSock库
WORD wVersionRequested;WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
int wsaret=WSAStartup(wVersionRequested,&wsaData);if(wsaret)
return;//创建SOCKET
SOCKET socketSrv;
socketSrv=socket(AF_INET,SOCK_STREAM,0);if(socketSrv==INVALID_SOCKET)
return;SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(87);
//绑定套接字
if(bind(socketSrv,(struct sockaddr*)&addrSrv,sizeof(SOCKADDR))){ //关闭连接
shutdown(socketSrv,1);closesocket(socketSrv);
WSACleanup();return;} //等待客户端连接
SOCKADDR_IN addrCli;int len=sizeof(SOCKADDR);//监听端口
if(listen(socketSrv,5)==SOCKET_ERROR){ printf(“监听失败!n”);} while(true){ //接受连接
SOCKET socketconn= accept(socketSrv,(SOCKADDR*)&addrCli, &len);
if(socketconn==SOCKET_ERROR)
{
cout
return;
}
cout
shutdown(socketSrv,1);closesocket(socketSrv);
WSACleanup();return;}----handle函数:
DWORD WINAPI handle(void *para){ //声明store函数,用来从磁盘中读取网页内容到内存
void store(string);SOCKET socketconn=(SOCKET)para;//连接成功后与客户端进行会话 char recvBuff[1024];string sendBuff;
string locDir;ifstream fp;//接收请求
if(recv(socketconn,recvBuff,1024,0)==SOCKET_ERROR)return 0;//读取http请求头
string recvBuffer=recvBuff;int posGet=recvBuffer.find(“GET”,0);int posHttp=recvBuffer.find(“HTTP”,0);for(int pos=posGet+4;pos
locDir.push_back('');
continue;} locDir.push_back(recvBuffer[pos]);} int len=locDir.length();//截取网页的文件名
string ine_str=locDir.substr(1,len-2);//从内存中获得该网页的内容
string allcontent=webhtml[ine_str];//如果在内存中找不到,则再从磁盘中把网页读入内存,然后再从内存中查找 if(allcontent==“”){ //调用store函数,从磁盘中重新读取网页内容 store(ine_str);//重新从内存中读取网页内容
allcontent=webhtml[ine_str];} //将读取的内容追加入sendBuff中 sendBuff.append(allcontent);fp.close();//响应请求,将页面信息发送到客户端
if(send(socketconn,sendBuff.c_str(),sendBuff.length(),0)==SOCKET_ERROR){
cout
return 0;} shutdown(socketconn,1);closesocket(socketconn);//关闭连接
return 0;}----Store()函数:
void store(string ine_str){
//如果内存中的网页个数大于100个,则把第一个移除
if(webhtml.size()>100){ map::iterator Iter=webhtml.begin();webhtml.erase(Iter);} string allchars=“”;//一个网页中所有的字符
char buffer[1024*10];//每次读取1024个字节到缓存 ifstream fp;//文件流
fp.open((loc_webpage+ine_str).c_str(),std::ios::binary);//打开指定文件 if(fp.fail())cout
fp.getline(buffer,1024*10);//从文件中读取1024个字节到缓冲区里面
allchars.append(buffer);//把缓存中的字节加到allchars后面
buffer[0]=' ';} } webhtml[ine_str]=allchars;//存储网页名字和内容,保存到内存中
fp.close();} 【运行结果】
----->客户端未请求之前
---->客户端发出请求(输入相应网址)
---->服务器端显示连接成功
客户端显示出网页内容
【出现问题】:当程序第一次执行主函数的while(true)的时候,输出“连接成功”后直接跳过QueueUserWorkItem()函数,即不执行此函数;但是当第二次执行while(true)循环的时候,却进入了QueueUserWorkItem()函数。出现的现象是第一次把网页内容送到客户端之前,显示两个”连接成功”。【原因及解决方法】:在错误的程序中,sockconn是在while(true)循环外面定义的,即执行所有的while(true)循环都是一个sockconn,这就导致了不同的客户端请求使用同一个sockconn的现象,所以出现了上面的错误。在每次的while(true)循环中都定义一个新的sockconn即可解决此问题。
【实验心得】在此次实验中,虽然编写的代码不多,但是有很多细节需要注意到。比如说空格问题,当截取网页的名称时就出现了多余空格的现象:不管我在客户端输入什么请求,服务器都不会返回内容给客户端。当我调试程序的时候才发现,每次截取网页名字的时候都会在字符串后面多余一个空格,这就导致了没有任何网页名字与之对应,所以服务器不会返回任何内容给客户端。空格问题是大问题,我已经深受其害两次了。