随笔-341  评论-2670  文章-0  trackbacks-0
    为了给C++的反射做Demo,不得不研究一下HTTP的协议。后来发现Windows自带了API可以用,于是就写了个小东西。程序打开之后,如果检测到【http://localhost:8080/vczh/FILENAME】这样子的请求,就将一个目录下面的东西读出来,然后返回。于是就可以用IE来运行某个地方的网页了。

    首先看效果图:


    这是一个只返回网页内容的HTTP服务器程序。
  1 #include <sdkddkver.h>
  2 #include <http.h>
  3 #include "..\..\..\..\VL++\Library\Platform\VL_Console.h"
  4 #include "..\..\..\..\VL++\Library\Data\VL_System.h"
  5 #include "..\..\..\..\VL++\Library\Data\VL_Stream.h"
  6 #include "..\..\..\..\VL++\Library\Data\VL_Communication.h"
  7 
  8 #pragma comment(lib,"Httpapi.lib")
  9 
 10 using namespace vl;
 11 using namespace vl::platform;
 12 using namespace vl::stream;
 13 using namespace vl::system;
 14 using namespace vl::communication;
 15 
 16 class HttpThread : public VL_Thread
 17 {
 18 protected:
 19     HANDLE                FHttpHandle;
 20     VByte                FBuffer[65536];
 21     PHTTP_REQUEST        FRequest;
 22     VUnicodeString        FWorkPath;
 23 
 24     VUnicodeString ToString(PCWChar Buffer)
 25     {
 26         return Buffer?Buffer:L"";
 27     }
 28 
 29     void Run()
 30     {
 31         while(!FNeedToTerminate)
 32         {
 33             ULONG Bytes=0;
 34             ULONG ErrorCode=0;
 35             if((ErrorCode=HttpReceiveHttpRequest(FHttpHandle,HTTP_NULL_ID,0,FRequest,sizeof(FBuffer),&Bytes,NULL))==NO_ERROR)
 36             {
 37                 VUnicodeString URL=ToString(FRequest->CookedUrl.pFullUrl);
 38                 VUnicodeString Query=ToString(FRequest->CookedUrl.pQueryString);
 39                 VInt PortPos=URL.Pos(L":8080/vczh/")+11;
 40                 VUnicodeString FilePath=FWorkPath+URL.SubString(PortPos,URL.Length()-PortPos-Query.Length());
 41                 GetConsole()->WriteLine(L"请求地址:"+URL);
 42                 GetConsole()->WriteLine(L"文件地址:"+FilePath);
 43 
 44                 HTTP_VERSION Version=HTTP_VERSION_1_1;
 45                 HTTP_RESPONSE Response;
 46                 memset(&Response,0,sizeof(Response));
 47                 Response.Version=Version;
 48 
 49                 if(VFSO_FileExists(FilePath))
 50                 {
 51                     VL_FileStream HtmlFile(FilePath,VL_FileStream::vomRead);
 52                     VBuffer Buffer=new VByte[(VInt)HtmlFile.Size()];
 53                     HtmlFile.Read(Buffer,(VInt)HtmlFile.Size());
 54 
 55                     HTTP_DATA_CHUNK Chunk;
 56                     Chunk.DataChunkType=HttpDataChunkFromMemory;
 57                     Chunk.FromMemory.BufferLength=(ULONG)HtmlFile.Size();
 58                     Chunk.FromMemory.pBuffer=Buffer;
 59 
 60                     Response.StatusCode=200;
 61                     Response.EntityChunkCount=1;
 62                     Response.pEntityChunks=&Chunk;
 63                     if((ErrorCode=HttpSendHttpResponse(FHttpHandle,FRequest->RequestId,HTTP_SEND_RESPONSE_FLAG_DISCONNECT,&Response,NULL,&Bytes,NULL,NULL,NULL,NULL))!=NO_ERROR)
 64                     {
 65                         GetConsole()->WriteLine(L"HttpSendHttpResponse发送页面不存在回复失败("+VUnicodeString((VInt)ErrorCode)+L")。");
 66                     }
 67 
 68                     delete[] Buffer;
 69                 }
 70                 else
 71                 {
 72                     Response.StatusCode=404;
 73                     if((ErrorCode=HttpSendHttpResponse(FHttpHandle,FRequest->RequestId,HTTP_SEND_RESPONSE_FLAG_DISCONNECT,&Response,NULL,&Bytes,NULL,NULL,NULL,NULL))!=NO_ERROR)
 74                     {
 75                         GetConsole()->WriteLine(L"HttpSendHttpResponse发送页面不存在回复失败("+VUnicodeString((VInt)ErrorCode)+L")。");
 76                     }
 77                 }
 78             }
 79             else
 80             {
 81                 GetConsole()->WriteLine(L"HttpReceiveHttpRequest失败("+VUnicodeString((VInt)ErrorCode)+L")。");
 82             }
 83         }
 84     }
 85 public:
 86     HttpThread(HANDLE HttpHandle , VUnicodeString WorkPath):VL_Thread(true,false)
 87     {
 88         FHttpHandle=HttpHandle;
 89         FRequest=(PHTTP_REQUEST)FBuffer;
 90         FWorkPath=WorkPath;
 91     }
 92 };
 93 
 94 void vlmain()
 95 {
 96     GetConsole()->SetTitle(L"Vczh HTTP Server");
 97     GetConsole()->SetTestMemoryLeaks(true);
 98     GetConsole()->SetPauseOnExit(true);
 99     VUnicodeString WorkPath=VFileName(GetConsole()->GetAppPath()).MakeAbsolute(L"..\\Web\\").GetStrW();
100     GetConsole()->WriteLine(L"网站:"+WorkPath);
101     GetConsole()->WriteLine(L"主机名称:"+GetHostName());
102     GetConsole()->WriteLine(L"主机地址:"+GetIpv4Address());
103 
104     ULONG ErrorCode=0;
105 
106     HTTPAPI_VERSION Version=HTTPAPI_VERSION_1;
107     if(HttpInitialize(Version,HTTP_INITIALIZE_SERVER,NULL)!=NO_ERROR)
108     {
109         GetConsole()->WriteLine(L"HttpInitialize失败。");
110         goto VCZH_HTTP_SERVER_INITIALIZE_FAIL;
111     }
112 
113     HANDLE HttpHandle=0;
114     if(HttpCreateHttpHandle(&HttpHandle,NULL)!=NO_ERROR)
115     {
116         GetConsole()->WriteLine(L"HttpCreateHttpHandle失败。");
117         goto VCZH_HTTP_SERVER_CREATE_HANDLE_FAIL;
118     }
119 
120     if(HttpAddUrl(HttpHandle,L"http://+:8080/vczh/",NULL)!=NO_ERROR)
121     {
122         GetConsole()->WriteLine(L"HttpAddUrl失败,需要使用管理员身份启动。");
123         goto VCZH_HTTP_SERVER_ADD_URL_FAIL;
124     }
125 
126     {
127         HttpThread Thread(HttpHandle,WorkPath);
128         Thread.Execute();
129         GetConsole()->WriteLine(L"按回车结束服务程序:");
130         GetConsole()->WaitForEnter();
131         Thread.SetNeedToTerminate(true);
132         Thread.WaitFor();
133     }
134 
135     if(HttpRemoveUrl(HttpHandle,L"http://+:8080/vczh/")!=NO_ERROR)
136     {
137         GetConsole()->WriteLine(L"HttpRemoveUrl失败。");
138     }
139 VCZH_HTTP_SERVER_ADD_URL_FAIL:
140 
141     if(!CloseHandle(HttpHandle))
142     {
143         GetConsole()->WriteLine(L"CloseHandle失败。");
144     }
145 VCZH_HTTP_SERVER_CREATE_HANDLE_FAIL:
146 
147     if(HttpTerminate(HTTP_INITIALIZE_SERVER,NULL)!=NO_ERROR)
148     {
149         GetConsole()->WriteLine(L"HttpTerminate失败。");
150     }
151 VCZH_HTTP_SERVER_INITIALIZE_FAIL:
152 
153     GetConsole()->WriteLine(L"Vczh HTTP Server执行结束。");
154 }
posted on 2009-06-29 05:19 陈梓瀚(vczh) 阅读(3779) 评论(4)  编辑 收藏 引用 所属分类: C++

评论:
# re: 残废版HTTP Server之小试牛刀 2009-06-29 17:09 | 巫云
崇拜……  回复  更多评论
  
# re: 残废版HTTP Server之小试牛刀 2009-07-06 09:19 | 余秋雨他老爹
博主是Delphi出身的哈  回复  更多评论
  
# re: 残废版HTTP Server之小试牛刀 2009-07-06 18:47 | 陈梓瀚(vczh)
@余秋雨他老爹
被你看出来了- -b  回复  更多评论
  
# re: 残废版HTTP Server之小试牛刀 2011-02-10 18:58 | loop
那几个goto看着不是很爽,呵呵。  回复  更多评论
  

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理