原文地址:https://www.cnblogs.com/mq0036/p/6656888.html
最近有个web的小项目,但公司的电脑无法安装IIS,所以就想自己来实现个Web server服务器,原本想了下,也就是socket处理http请求,于是就在博客园中搜索了“socket实现web server”,结果还真搜索到一些文章,于是从中找了几个做参考,如下:
C#中自己动手创建一个Web Server(非Socket实现)
其他的这里就不一一列出了,感兴趣的可以自己搜索看看。
所以我根据他们的代码,然后自己在修改符合自己使用的情况,初次版本就出来了,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets;namespace socket_webServer
{
class Program
{
static Socket _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //侦听socket
static string webRoot = @"C:UsersjackDesktop</span>";
static string defaultPage = "index.html,home.html";</span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span><span style="color: #000000;">[] args) { webRoot </span>= <span style="color: #800000;">@"</span><span style="color: #800000;">C:\_jackDevCode</span><span style="color: #800000;">"</span><span style="color: #000000;">; _socket.Bind(</span><span style="color: #0000ff;">new</span> IPEndPoint(IPAddress.Any, <span style="color: #800080;">8080</span><span style="color: #000000;">)); _socket.Listen(</span><span style="color: #800080;">100</span><span style="color: #000000;">); _socket.BeginAccept(</span><span style="color: #0000ff;">new</span> AsyncCallback(OnAccept), _socket); <span style="color: #008000;">//</span><span style="color: #008000;">开始接收来自浏览器的http请求(其实是socket连接请求)</span> writeLog(<span style="color: #800000;">"</span><span style="color: #800000;">Socket Web Server 已启动监听!</span><span style="color: #800000;">"</span> + Environment.NewLine + <span style="color: #800000;">"</span><span style="color: #800000;"> 监听端口:</span><span style="color: #800000;">"</span> +<span style="color: #000000;"> ((IPEndPoint)_socket.LocalEndPoint).Port); Console.ReadKey(); } </span><span style="color: #808080;">///</span> <span style="color: #808080;"><summary></span> <span style="color: #808080;">///</span><span style="color: #008000;"> 接受处理http的请求 </span><span style="color: #808080;">///</span> <span style="color: #808080;"></summary></span> <span style="color: #808080;">///</span> <span style="color: #808080;"><param name="ar"></param></span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> OnAccept(IAsyncResult ar) { </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { Socket socket </span>= ar.AsyncState <span style="color: #0000ff;">as</span><span style="color: #000000;"> Socket; Socket web_client </span>= socket.EndAccept(ar); <span style="color: #008000;">//</span><span style="color: #008000;">接收到来自浏览器的代理socket </span><span style="color: #008000;">//</span><span style="color: #008000;">NO.1 并行处理http请求</span> socket.BeginAccept(<span style="color: #0000ff;">new</span> AsyncCallback(OnAccept), socket); <span style="color: #008000;">//</span><span style="color: #008000;">开始下一次http请求接收 (此行代码放在NO.2处时,就是串行处理http请求,前一次处理过程会阻塞下一次请求处理)</span> <span style="color: #0000ff;">byte</span>[] recv_Buffer = <span style="color: #0000ff;">new</span> <span style="color: #0000ff;">byte</span>[<span style="color: #800080;">1024</span> * <span style="color: #800080;">640</span><span style="color: #000000;">]; </span><span style="color: #0000ff;">int</span> recv_Count = web_client.Receive(recv_Buffer); <span style="color: #008000;">//</span><span style="color: #008000;">接收浏览器的请求数据</span> <span style="color: #0000ff;">string</span> recv_request = Encoding.UTF8.GetString(recv_Buffer, <span style="color: #800080;">0</span><span style="color: #000000;">, recv_Count); writeLog(</span><span style="color: #800000;">"</span><span style="color: #800000;">Data Request : </span><span style="color: #800000;">"</span> + recv_request); <span style="color: #008000;">//</span><span style="color: #008000;">将请求显示到界面 </span><span style="color: #008000;">//</span><span style="color: #008000;">Resolve(recv_request, web_client); </span><span style="color: #008000;">//</span><span style="color: #008000;">解析、路由、处理</span> <span style="color: #0000ff;">byte</span>[] cont =<span style="color: #000000;"> pageHandle(RouteHandle(recv_request)); sendPageContent(cont, web_client); </span><span style="color: #008000;">//</span><span style="color: #008000;">NO.2 串行处理http请求</span>
}
catch (Exception ex)
{
writeLog("处理http请求时出现异常!" + Environment.NewLine + " " + ex.Message);
}
}</span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> sendPageContent(<span style="color: #0000ff;">byte</span><span style="color: #000000;">[] pageContent, Socket response) { </span><span style="color: #0000ff;">string</span> statusline = <span style="color: #800000;">"</span><span style="color: #800000;">HTTP/1.1 200 OK </span><span style="color: #800000;">"</span>; <span style="color: #008000;">//</span><span style="color: #008000;">状态行</span> <span style="color: #0000ff;">byte</span>[] statusline_to_bytes =<span style="color: #000000;"> Encoding.UTF8.GetBytes(statusline); </span><span style="color: #0000ff;">string</span> content = <span style="color: #800000;">"</span><span style="color: #800000;"><html></span><span style="color: #800000;">"</span> + <span style="color: #800000;">"</span><span style="color: #800000;"><head></span><span style="color: #800000;">"</span> + <span style="color: #800000;">"</span><span style="color: #800000;"><title>socket webServer -- Login</title></span><span style="color: #800000;">"</span> + <span style="color: #800000;">"</span><span style="color: #800000;"></head></span><span style="color: #800000;">"</span> + <span style="color: #800000;">"</span><span style="color: #800000;"><body></span><span style="color: #800000;">"</span> + <span style="color: #800000;">"</span><span style="color: #800000;"><div style="text-align:center"></span><span style="color: #800000;">"</span> + <span style="color: #800000;">"</span><span style="color: #800000;">欢迎您!</span><span style="color: #800000;">"</span> + <span style="color: #800000;">""</span> + <span style="color: #800000;">"</span><span style="color: #800000;">,今天是 </span><span style="color: #800000;">"</span> + DateTime.Now.ToLongDateString() + <span style="color: #800000;">"</span><span style="color: #800000;"></div></span><span style="color: #800000;">"</span> + <span style="color: #800000;">"</span><span style="color: #800000;"></body></span><span style="color: #800000;">"</span> + <span style="color: #800000;">"</span><span style="color: #800000;"></html></span><span style="color: #800000;">"</span>; <span style="color: #008000;">//</span><span style="color: #008000;">内容</span> <span style="color: #0000ff;">byte</span>[] content_to_bytes =<span style="color: #000000;"> pageContent; </span><span style="color: #0000ff;">string</span> header = <span style="color: #0000ff;">string</span>.Format(<span style="color: #800000;">"</span><span style="color: #800000;">Content-Type:text/html;charset=UTF-8 Content-Length:{0} </span><span style="color: #800000;">"</span><span style="color: #000000;">, content_to_bytes.Length); </span><span style="color: #0000ff;">byte</span>[] header_to_bytes = Encoding.UTF8.GetBytes(header); <span style="color: #008000;">//</span><span style="color: #008000;">应答头</span>
response.Close();response.Send(statusline_to_bytes); </span><span style="color: #008000;">//</span><span style="color: #008000;">发送状态行</span> response.Send(header_to_bytes); <span style="color: #008000;">//</span><span style="color: #008000;">发送应答头</span> response.Send(<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">byte</span>[] { (<span style="color: #0000ff;">byte</span>)<span style="color: #800000;">'</span><span style="color: #800000;"> </span><span style="color: #800000;">'</span>, (<span style="color: #0000ff;">byte</span>)<span style="color: #800000;">'</span><span style="color: #800000;"> </span><span style="color: #800000;">'</span> }); <span style="color: #008000;">//</span><span style="color: #008000;">发送空行</span> response.Send(content_to_bytes); <span style="color: #008000;">//</span><span style="color: #008000;">发送正文(html)</span>
} </span><span style="color: #808080;">///</span> <span style="color: #808080;"><summary></span> <span style="color: #808080;">///</span> <span style="color: #808080;">///</span> <span style="color: #808080;"></summary></span> <span style="color: #808080;">///</span> <span style="color: #808080;"><param name="request"></param></span> <span style="color: #808080;">///</span> <span style="color: #808080;"><returns></returns></span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">string</span> RouteHandle(<span style="color: #0000ff;">string</span><span style="color: #000000;"> request) { </span><span style="color: #0000ff;">string</span> retRoute = <span style="color: #800000;">""</span><span style="color: #000000;">; </span><span style="color: #0000ff;">string</span>[] strs = request.Split(<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">string</span>[] { <span style="color: #800000;">"</span><span style="color: #800000;"> </span><span style="color: #800000;">"</span> }, StringSplitOptions.None); <span style="color: #008000;">//</span><span style="color: #008000;">以“换行”作为切分标志</span> <span style="color: #0000ff;">if</span> (strs.Length > <span style="color: #800080;">0</span>) <span style="color: #008000;">//</span><span style="color: #008000;">解析出请求路径、post传递的参数(get方式传递参数直接从url中解析)</span>
{
string[] items = strs[0].Split(' '); //items[1]表示请求url中的路径部分(不含主机部分)
string pageName = items[1];
string post_data = strs[strs.Length - 1]; //最后一项
//Dictionary<string, string> dict = ParameterHandle(strs);
retRoute = pageName + (post_data.Length > 0 ? "?" + post_data : "");
}</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> retRoute; } </span><span style="color: #808080;">///</span> <span style="color: #808080;"><summary></span> <span style="color: #808080;">///</span><span style="color: #008000;"> 按照HTTP协议格式,解析浏览器发送的请求字符串 </span><span style="color: #808080;">///</span> <span style="color: #808080;"></summary></span> <span style="color: #808080;">///</span> <span style="color: #808080;"><param name="strs"></param></span> <span style="color: #808080;">///</span> <span style="color: #808080;"><returns></returns></span> <span style="color: #0000ff;">static</span> Dictionary<<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">string</span>> ParameterHandle(<span style="color: #0000ff;">string</span><span style="color: #000000;">[] strs) { Dictionary</span><<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">string</span>> param = <span style="color: #0000ff;">new</span> Dictionary<<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">string</span>><span style="color: #000000;">(); </span><span style="color: #0000ff;">if</span> (strs.Length > <span style="color: #800080;">0</span>) <span style="color: #008000;">//</span><span style="color: #008000;">解析出请求路径、post传递的参数(get方式传递参数直接从url中解析)</span>
{
if (strs.Contains("")) //包含空行 说明存在post数据
{
string post_data = strs[strs.Length - 1]; //最后一项
if (post_data != "")
{
string[] post_datas = post_data.Split('&');
foreach (string s in post_datas)
{
param.Add(s.Split('=')[0], s.Split('=')[1]);
}
}
}
}
return param;
}</span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">byte</span>[] pageHandle(<span style="color: #0000ff;">string</span><span style="color: #000000;"> pagePath) { </span><span style="color: #0000ff;">byte</span>[] pageContent = <span style="color: #0000ff;">null</span><span style="color: #000000;">; webRoot </span>= webRoot.TrimEnd(<span style="color: #800000;">'</span><span style="color: #800000;">/</span><span style="color: #800000;">'</span>, <span style="color: #800000;">'</span><span style="color: #800000;">\</span><span style="color: #800000;">'</span><span style="color: #000000;">); pagePath </span>= pagePath.TrimEnd(<span style="color: #800000;">'</span><span style="color: #800000;">/</span><span style="color: #800000;">'</span>, <span style="color: #800000;">'</span><span style="color: #800000;">\</span><span style="color: #800000;">'</span><span style="color: #000000;">); </span><span style="color: #0000ff;">if</span> (pagePath.Length==<span style="color: #800080;">0</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">string</span> page <span style="color: #0000ff;">in</span> defaultPage.Split(<span style="color: #800000;">'</span><span style="color: #800000;">,</span><span style="color: #800000;">'</span><span style="color: #000000;">)) { </span><span style="color: #0000ff;">if</span> (System.IO.File.Exists(webRoot +<span style="color: #000000;"> page)) { pagePath </span>=<span style="color: #000000;"> page; </span><span style="color: #0000ff;">break</span><span style="color: #000000;">; } } } </span><span style="color: #0000ff;">if</span> (System.IO.File.Exists(webRoot +<span style="color: #000000;"> pagePath)) pageContent </span>= System.IO.File.ReadAllBytes(webRoot +<span style="color: #000000;"> pagePath); </span><span style="color: #0000ff;">if</span> (pageContent == <span style="color: #0000ff;">null</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">string</span> content =<span style="color: #000000;"> notExistPage(); pageContent </span>=<span style="color: #000000;"> Encoding.UTF8.GetBytes(content); } </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> pageContent; } </span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> writeLog(<span style="color: #0000ff;">string</span><span style="color: #000000;"> msg) { Console.WriteLine(</span><span style="color: #800000;">"</span> <span style="color: #800000;">"</span> +<span style="color: #000000;"> msg); } </span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">string</span><span style="color: #000000;"> notExistPage() { </span><span style="color: #0000ff;">string</span> cont = <span style="color: #800000;">@"</span><span style="color: #800000;"><!DOCTYPE HTML>
<html>
<head> <link rel='stylesheet' type='text/css' href='NewErrorPageTemplate.css' > <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'> <title>This page can&rsquo;t be displayed</title> <script src='errorPageStrings.js' language='javascript' type='text/javascript'> </script> <script src='httpErrorPagesScripts.js' language='javascript' type='text/javascript'> </script> </head> <body onLoad='javascript:getInfo();'> <div id='contentContainer' class='mainContent'> <div id='mainTitle' class='title'>This page can&rsquo;t be displayed</div> <div class='taskSection' id='taskSection'> <ul id='cantDisplayTasks' class='tasks'> <li id='task1-1'>Make sure the web address <span id='webpage' class='webpageURL'></span>is correct.</li> <li id='task1-2'>Look for the page with your search engine.</li> <li id='task1-3'>Refresh the page in a few minutes.</li> </ul> <ul id='notConnectedTasks' class='tasks' style='display:none'> <li id='task2-1'>Check that all network cables are plugged in.</li> <li id='task2-2'>Verify that airplane mode is turned off.</li> <li id='task2-3'>Make sure your wireless switch is turned on.</li> <li id='task2-4'>See if you can connect to mobile broadband.</li> <li id='task2-5'>Restart your router.</li> </ul> </div> <div><button id='diagnose' class='diagnoseButton' onclick='javascript:diagnoseConnectionAndRefresh(); return false;'>Fix connection problems</button></div> </div> </body>
</html>";
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> cont; } }
}
这个web server的雏形就出来了,以后有需要的功能在慢慢往上添加吧
参考文章:
Socket网络编程--简单Web服务器各章节传送门
Socket网络编程--简单Web服务器(1) http://www.cnblogs.com/wunaozai/p/3926033.html
Socket网络编程--简单Web服务器(2) http://www.cnblogs.com/wunaozai/p/3936295.html
Socket网络编程--简单Web服务器(3) http://www.cnblogs.com/wunaozai/p/3943952.html
Socket网络编程--简单Web服务器(4) http://www.cnblogs.com/wunaozai/p/3945218.html
Socket网络编程--简单Web服务器(5) http://www.cnblogs.com/wunaozai/p/3946486.html
Socket网络编程--简单Web服务器(6) http://www.cnblogs.com/wunaozai/p/3949324.html
源码下载: https://files.cnblogs.com/wunaozai/WebServer.zip