由于经常需要这样一些场合,让应用程序能够响应简单的HTTP请求,以实现一些功能,所以就做了一个这样的小型HTTP服务器库。库使用C++实现,编译成MT,Release模式的静态链接库,欢迎有兴趣的朋友使用。该库仅适用Windows操作系统。
下面是库的定义:
#ifndef __HOVERLEES_TINY_HTTPD_H #define __HOVERLEES_TINY_HTTPD_H #include <Windows.h> #include <WinSock.h> #include <map> struct HoverCompare{ bool operator()(const char* x, const char* y){ return strcmp(x,y)<0; } }; /** * @name 嵌入应用程序的简单HTTP服务器 * @author Hoverlees http://www.hoverlees.com * 调用者继承这个类以处理HTTP请求 */ class TinyHttpd{ private: static bool inited; static WSADATA wsaData; static DWORD WINAPI ServerThreadProc(void* lpParameter); static DWORD WINAPI ClientThreadProc(void* lpParameter); protected: const static int STATUS_IDLE=0; const static int STATUS_RUNNING=1; typedef std::map<char*,char*,HoverCompare> hmap; int status; SOCKET serverSocket; sockaddr_in address; public: TinyHttpd(); /** * 启动服务器 * @param bindPort 梆定的HTTP端口 * @param bindIP 梆定IP地址 * @return 成功状态 */ bool startServer(unsigned short bindPor=80,const char* bindIP="0.0.0.0"); /** * 停止服务器 * @return 成功状态 */ bool stopServer(); /** * 向客户端发送应答,每一个请求只能调用一次这个函数。 * @param clientSocket 客户端socket * @param mem 应答的内容 * @param memSize 应答内容大小 * @param response_headers HTTP响应头,如果不设置,可以为NULL * @return 操作结果 */ bool sendResponse(SOCKET clientSocket,const char* mem,int memSize,hmap* response_headers); /** * 回调方法,当服务器收到HTTP请求时,调用这个函数,注意TinyHttpd只支持GET请求 * @param clientSocket客户端socket,一般不直接操作,而是传入到sendResponse中。 * @param uri 请求uri,如客户端请求 /hoverlees?a=1&b=2 时,uri是 /hoverlees * @param params 请求参数,这是HTTP get参数key=>value的map对象.如 params["a"]=1 * @return 如果用户处理了该请求,返回true,这时服务器响应200,如果没处理请求返回false ,服务器响应404 */ virtual bool onHttpRequest(SOCKET clientSocket,const char* uri,hmap* params){return false;} }; #endif
使用示例如下:
#include <iostream> #include <cstdlib> #include "TinyHttpd.h" using namespace std; #pragma comment(lib,"TinyHttpd.lib") class MyHttpd:public TinyHttpd{ public: MyHttpd():TinyHttpd(){ }; virtual bool onHttpRequest(SOCKET clientSocket,const char* uri,hmap* params){ void* mem; FILE* fp; hmap headers; int fsize; //可以先在这儿对uri指定的文件进行判断,如果文件存在,可以直接输出文件,这样就完全实现了一个静态网页的服务器。 if(strcmp(uri,"/hoverlees")==0){ if((*params)["hello"]){ //如果设置了hello参数,如:http://localhost/hoverlees?hello=1 this->sendResponse(clientSocket,"Hello World!",12,0); } else this->sendResponse(clientSocket,"Hoverlees",9,NULL); } else if(strcmp(uri,"/pic")==0){ //http://localhost/pic fp=fopen("./1.png","rb"); fseek(fp,0,SEEK_END); fsize=ftell(fp); mem=malloc(fsize); fseek(fp,0,SEEK_SET); fread(mem,1,fsize,fp); fclose(fp); headers["Content-Type"]="image/png"; this->sendResponse(clientSocket,(char*)mem,fsize,&headers); free(mem); } else if(strcmp(uri,"/")==0){ char* html="<html><body><a href='/hoverlees'>hoverlees</a> <a href='/pic'>Picture</a></body></html>"; this->sendResponse(clientSocket,html,strlen(html),NULL); } else return false; return true; } }; int main(int argc,char* argv[]){ //创建服务器 MyHttpd* httpd=new MyHttpd(); //启动服务器 httpd->startServer(80); while(1){ Sleep(10000); } return 0; }
相关的库文件和头文件在这里下载.test_app