bool CHttpProtocol::StartHttpSrv()
{
//...
WSAStartup(wVersionRequested,&wsaData);//启动Socket命令,version就是版本,wsaData用来接收socket实现细节
m_listenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,NULL,0,WSA_FLAG_OVERLAPPED)//create Socket
bind(m_listenSocket,(LPSOCKADDR)&sockAddr,sizeof(struct sockaddr))//将套接字和sock地址绑定,sock采用(LPSOCKADDR)数据结构
listen(m_listenSocket,SOMAXCONN);//套接字监听,为客户连接创建等待队列,队列最大长度是SOMAXCONN = 128
m_pListenThread = AfxBeginThread(ListenThread,this);//创建线程,客户处理模块在ListenThread实现,listenthread 是一个函数
//...
}
typedef struct REQUEST
{
SOCKET socket; //请求socket
int nMethod; //请求的使用方法,eg get,post
DWORD dwRecv; //收到的字节数
DWORD dwSend; //发送的字节数
HANDLE hFile; //请求的文件
char szFileNamep[_MAX_PATH]; //文件的相对路径
char postfix[10]; //存储请求文件的扩展名
char StatuCodeReason[100]; //头部的status cod 以及 reason-phrase
void* pHttpProtocol; //指向类CHttpProtocol的指针
hExit //退出
}REQUEST, *PREQUEST;
//线程ListenThread的实现
UINT CHttpProtocol::ListenThread(LPVOID param)
{
CHttpProtocol *pHttpProtocol = (CHttpProtocol *)param;
PREQUEST pReq; //指向request结构的指针
SOCKET socketClient; //客户机连接的套接字
SOCKADDR_IN sockAddr; //Sock 地址
int nLen; //记录sockaddr_in的长度
while(1)
{
nLen = sizeof(SOCKADDR_IN);
socketClient = accpet(pHttpProtocol->m_listenSocket,(LPSOCKADDR)&SockAddr,&nLen);//套接字等待连接,返回对应已接受的客户连接的套接字
pReq = new REQUEST ; //创建 REQUEST 结构传递给客户处理线程
//初始化REQUEST结构
pReq->hExit = pHttpProtocol -> m_hExit;
pReq->Socket = socketClient;
pReq ->hFile = INVALID_HANDLE_VALUE;
pReq->dwRecv = 0;
pReq->dwSend = 0;
pReq->pHttpProtocol = pHttpProtocol;
//创建客户处理线程,处理request
AfxBeginThread( ClientThread, pReq ); //clientthread 是一个函数,在线面
}
}
/*
*ClientThread 负责分析客户请求中各个协议参数,对分析结果
*查找资源,生成相响应,发送响应
**/
UNIT CHttpProtocol::ClientThread(LPVOID param)
{
BYTE buf[1024];
PREQUEST pReq = (PREQUEST)PARAM; //pReq表示从客户端传来的请求
CHttpProtocol *pHttpProtocol = (CHttpProtocol *)pReq->pHttpProtocol;//获取pReq的http协议对象
pHttpProtocol->RecvRequest(pReq, buf,sizeof(buf));//接收数据,放入缓存buf中
pHttpProtocol->Analyze(pReq,buf);//分析request信息,判断请求类型,获取Request-URI;Request-URI可以获得链接的各部分内容
pHttpProtocol->SendHeader(pReq);//发送200(ok)等响应消息
if(Req->nMethod == METHOD_GET)//本程序只支持GET操作,如果是GET,则向客户端传送请求数据
{
pHttpProtocol->SendFile(pReq);//向客户端传送请求的数据
}
pHttpProtocol->Disconnect(pReq);//断开连接
delete pReq;//删除客户端的request
return 0;
}
//Analyze函数
int CHttpProtocol::Analyze(PREQUEST pReq, LPBYTE pBuf)
{
//分析接收的信息
char szSeps[]='\n';
char * cpTOKEN;
if(strstr((const char *)pBuf,"..")!=NULL);//防止非法请求,strstr判断后一个参数是否是前一个参数
{
strcpy(pReq->StatuCodeReason,HTTP_STATUS_BADREQUEST);//返回错误状态码“400 Bad Requst”
return "1";
}
cpToken = strtok((char *)pBuf,szSeps);//缓存中字符串分解为一组标记串,就是将pBuf分解为szSeps
if(!_stricmp(cpToken,"GET"))//只查找get,因为本server只支持get。_stricmp()不区分大小写比较两个字符串,相同返回值为0,查找cpToken里面是否有get
{
pReq->nMethod = METHOD_GET
}
else
{
//返回错误状态码 501 Not Implemented
strcpy(pReq->StatuCodeReason,HTTP_STATUS_NOTIMPLEMENTED)
return 1;
}
//获取request-uri
cpToken = strtok(NULL,szSeps);//第二次调用该函数,结果返回分割一句后面的字符串(获取文件名)
if(cpToken == NULL)
{
//返回错误状态码"400 Bad Request"
}
strcpy(pReq->szFilename,m_strRootDir);
if(strlen(cpToken)>1)
{
strcat(pReq->szFilename,cpToken);//把文件名添加到路径结尾处形成完整路径
}
else
{
strcat(pReq->szFilename,"/index.html");//默认请求为主页
}
return 0;
}
//SendHeader 函数用于发送响应信息,200(ok)等等,SendFile函数用于发送用户请求的文件
/*
*【SendHeader函数的重要的函数有:】
*FileExist(pReq) //查找请求的文件,文件不存在则return;
*GetCurrentTime((char*)curTime);//获取当前时间
*GetFileSize(pReq->hFile,NULL);//获取文件长度
*GetLastModified(pReq->hFile,(char *)last_modified);//获取文件last-modified时间
*GetContentType(pReq,(char *)ContentType);//获取文件的类型
*send(pReq->Socket,Header,strlen(Header),0);//Header包含了响应信息,其中有状态,时间,server,Content-type,长度和lastmodified
*
*【SendFile函数的重要函数有】
*FileExist(pReq) //查找请求的文件,文件不存在则return;
*在死循环里,fRet = ReadFile(pReq->hFile,buf,sizeof(buf),&dwRead,NULL)从hFile读到buf中,dwRead用来标记发送是否完成。
*如果fRet为0,则发出错误信息HTTP_STATUS_SERVERERROR给pReq->Socket
*如果 dwRead = 0,则返回,即跳出死循环,dwRead用来标记发送是否完成。
*SendBuffer(pReq,buf,dwRead);将客户端请求的内容buf发送给客户端
*CloseHandle(pReq->hFile)关闭发送文件
**/
webserver实现伪代码
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 分治法 我们首先先介绍分治法。分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题...
- 分支结构 略 循环结构 求近似的圆周率 C C++ Java Python 求近似的自然对数e C C++ Jav...