这个简单的代码已经可以实现用于小白机器人的网络请求处理了,因为大致只用到GET和POST两种HTTP方法,只需要在GetContext方法里判断GET、POST方法,然后分别给出响应就可以了。
但是我们的目的是开发一个真正的网络服务器,当然不能只满足于这样一个专用的服务器,我们要的是可以提供网页服务的服务器。
那就继续吧。
根据我的研究,提供网页访问服务的服务器做起来确实有一点麻烦,因为需要处理的东西很多。需要根据浏览器请求的不同文件给出不同响应,处理Cookies,还要处理编码,还有各种出错的处理。
首先我们要确定一下我们的服务器要提供哪些文件的访问服务。
这里我用一个字典结构来保存。
/// <summary>
/// MIME类型
/// </summary>
public Dictionary<string, string> MIME_Type = new Dictionary<string, string>()
{
{ "htm", "text/html" },
{ "html", "text/html" },
{ "php", "text/html" },
{ "xml", "text/xml" },
{ "json", "application/json" },
{ "txt", "text/plain" },
{ "js", "application/x-javascript" },
{ "css", "text/css" },
{ "bmp", "image/bmp" },
{ "ico", "image/ico" },
{ "png", "image/png" },
{ "gif", "image/gif" },
{ "jpg", "image/jpeg" },
{ "jpeg", "image/jpeg" },
{ "webp", "image/webp" },
{ "zip", "application/zip"},
{ "*", "*/*" }
};
剧透一下:其中有PHP类型是我们后面要使用CGI接入的方式使我们的服务器支持PHP。
我在QFramework中封装了一个QHttpWebServer模块,这是其中的启动代码。
/// <summary>
/// 启动本地网页服务器
/// </summary>
/// <param name="webroot">网站根目录</param>
/// <returns></returns>
public bool Start(string webroot)
{
//触发事件
if (OnServerStart != null)
OnServerStart(httpListener);
WebRoot = webroot;
try
{
//监听端口
httpListener.Prefixes.Add("http://www.easck.com//开始异步接收request请求
}
catch (Exception ex)
{
Qdb.Error(ex.Message, QDebugErrorType.Error, "Start");
return false;
}
return true;
}
现在把网页服务器的核心处理代码贴出来。
这个代码只是做了基本的处理,对于网站的主页只做了html后缀的识别。
后来我在QFramework中封装的模块做了更多的细节处理。
/// <summary>
/// 网页服务器相应处理
/// </summary>
/// <param name="ar"></param>
private void onWebResponse(IAsyncResult ar)
{
byte[] responseByte = null; //响应数据
HttpListener httpListener = ar.AsyncState as HttpListener;
HttpListenerContext context = httpListener.EndGetContext(ar); //接收到的请求context(一个环境封装体)
httpListener.BeginGetContext(new AsyncCallback(onWebResponse), httpListener); //开始 第二次 异步接收request请求
//触发事件
if (OnGetRawContext != null)
OnGetRawContext(context);
HttpListenerRequest request = context.Request; //接收的request数据
HttpListenerResponse response = context.Response; //用来向客户端发送回复
//触发事件
if (OnGetRequest != null)
OnGetRequest(request, response);
if (rawUrl == "" || rawUrl == "/") //单纯输入域名或主机IP地址
fileName = WebRoot + @"index.html";
else if (rawUrl.IndexOf('.') == -1) //不带扩展名,理解为文件夹
fileName = WebRoot + @"" + rawUrl.SubString(1) + @"index.html";
else
{
int fileNameEnd = rawUrl.IndexOf('?');
if (fileNameEnd > -1)
fileName = rawUrl.Substring(1, fileNameEnd - 1);
fileName = WebRoot + @"" + rawUrl.Substring(1);
}
//处理请求文件名的后缀
string fileExt = Path.GetExtension(fileName).Substring(1);
if (!File.Exists(fileName))
{
responseByte = Encoding.UTF8.GetBytes("404 Not Found!");
response.StatusCode = (int)HttpStatusCode.NotFound;
}
else
{
try
{
responseByte = File.ReadAllBytes(fileName);
response.StatusCode = (int)HttpStatusCode.OK;
}
catch (Exception ex)
{
Qdb.Error(ex.Message, QDebugErrorType.Error, "onWebResponse");
response.StatusCode = (int)HttpStatusCode.InternalServerError;
}
}
if (MIME_Type.ContainsKey(fileExt))
response.ContentType = MIME_Type[fileExt];
else
response.ContentType = MIME_Type["*"];
response.Cookies = request.Cookies; //处理Cookies
response.ContentEncoding = Encoding.UTF8;
using (Stream output = response.OutputStream) //发送回复
{
try
{
output.Write(responseByte, 0, responseByte.Length);
}
catch (Exception ex)
{
Qdb.Error(ex.Message, QDebugErrorType.Error, "onWebResponse");
response.StatusCode = (int)HttpStatusCode.InternalServerError;
}
}
}










