C#中使用Socket实现简单Web服务器
原文地址: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:\Users\jack\Desktop</span>";
static string defaultPage = "index.html,home.html";
</span><span >static</span> <span >void</span> Main(<span >string</span><span >[] args)
{
webRoot </span>= <span >@"</span><span >C:\_jack\DevCode</span><span >"</span><span >;
_socket.Bind(</span><span >new</span> IPEndPoint(IPAddress.Any, <span >8080</span><span >));
_socket.Listen(</span><span >100</span><span >);
_socket.BeginAccept(</span><span >new</span> AsyncCallback(OnAccept), _socket); <span >//</span><span >开始接收来自浏览器的http请求(其实是socket连接请求)</span>
writeLog(<span >"</span><span >Socket Web Server 已启动监听!</span><span >"</span> + Environment.NewLine + <span >"</span><span > 监听端口:</span><span >"</span> +<span > ((IPEndPoint)_socket.LocalEndPoint).Port);
Console.ReadKey();
}
</span><span >///</span> <span ><summary></span>
<span >///</span><span > 接受处理http的请求
</span><span >///</span> <span ></summary></span>
<span >///</span> <span ><param name="ar"></param></span>
<span >static</span> <span >void</span><span > OnAccept(IAsyncResult ar)
{
</span><span >try</span><span >
{
Socket socket </span>= ar.AsyncState <span >as</span><span > Socket;
Socket web_client </span>= socket.EndAccept(ar); <span >//</span><span >接收到来自浏览器的代理socket
</span><span >//</span><span >NO.1 并行处理http请求</span>
socket.BeginAccept(<span >new</span> AsyncCallback(OnAccept), socket); <span >//</span><span >开始下一次http请求接收 (此行代码放在NO.2处时,就是串行处理http请求,前一次处理过程会阻塞下一次请求处理)</span>
<span >byte</span>[] recv_Buffer = <span >new</span> <span >byte</span>[<span >1024</span> * <span >640</span><span >];
</span><span >int</span> recv_Count = web_client.Receive(recv_Buffer); <span >//</span><span >接收浏览器的请求数据</span>
<span >string</span> recv_request = Encoding.UTF8.GetString(recv_Buffer, <span >0</span><span >, recv_Count);
writeLog(</span><span >"</span><span >Data Request : </span><span >"</span> + recv_request); <span >//</span><span >将请求显示到界面
</span><span >//</span><span >Resolve(recv_request, web_client); </span><span >//</span><span >解析、路由、处理</span>
<span >byte</span>[] cont =<span > pageHandle(RouteHandle(recv_request));
sendPageContent(cont, web_client);
</span><span >//</span><span >NO.2 串行处理http请求</span>
}
catch (Exception ex)
{
writeLog("处理http请求时出现异常!" + Environment.NewLine + "\t" + ex.Message);
}
}
</span><span >static</span> <span >void</span> sendPageContent(<span >byte</span><span >[] pageContent, Socket response)
{
</span><span >string</span> statusline = <span >"</span><span >HTTP/1.1 200 OK\r\n</span><span >"</span>; <span >//</span><span >状态行</span>
<span >byte</span>[] statusline_to_bytes =<span > Encoding.UTF8.GetBytes(statusline);
</span><span >string</span> content =
<span >"</span><span ><html></span><span >"</span> +
<span >"</span><span ><head></span><span >"</span> +
<span >"</span><span ><title>socket webServer -- Login</title></span><span >"</span> +
<span >"</span><span ></head></span><span >"</span> +
<span >"</span><span ><body></span><span >"</span> +
<span >"</span><span ><div text-align:center\"></span><span >"</span> +
<span >"</span><span >欢迎您!</span><span >"</span> + <span >""</span> + <span >"</span><span >,今天是 </span><span >"</span> + DateTime.Now.ToLongDateString() +
<span >"</span><span ></div></span><span >"</span> +
<span >"</span><span ></body></span><span >"</span> +
<span >"</span><span ></html></span><span >"</span>; <span >//</span><span >内容</span>
<span >byte</span>[] content_to_bytes =<span > pageContent;
</span><span >string</span> header = <span >string</span>.Format(<span >"</span><span >Content-Type:text/html;charset=UTF-8\r\nContent-Length:{0}\r\n</span><span >"</span><span >, content_to_bytes.Length);
</span><span >byte</span>[] header_to_bytes = Encoding.UTF8.GetBytes(header); <span >//</span><span >应答头</span>
response.Send(statusline_to_bytes); </span><span >//</span><span >发送状态行</span>
response.Send(header_to_bytes); <span >//</span><span >发送应答头</span>
response.Send(<span >new</span> <span >byte</span>[] { (<span >byte</span>)<span >'</span><span >\r</span><span >'</span>, (<span >byte</span>)<span >'</span><span >\n</span><span >'</span> }); <span >//</span><span >发送空行</span>
response.Send(content_to_bytes); <span >//</span><span >发送正文(html)</span>
response.Close();
}
</span><span >///</span> <span ><summary></span>
<span >///</span>
<span >///</span> <span ></summary></span>
<span >///</span> <span ><param name="request"></param></span>
<span >///</span> <span ><returns></returns></span>
<span >static</span> <span >string</span> RouteHandle(<span >string</span><span > request)
{
</span><span >string</span> retRoute = <span >""</span><span >;
</span><span >string</span>[] strs = request.Split(<span >new</span> <span >string</span>[] { <span >"</span><span >\r\n</span><span >"</span> }, StringSplitOptions.None); <span >//</span><span >以“换行”作为切分标志</span>
<span >if</span> (strs.Length > <span >0</span>) <span >//</span><span >解析出请求路径、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 >return</span><span > retRoute;
}
</span><span >///</span> <span ><summary></span>
<span >///</span><span > 按照HTTP协议格式,解析浏览器发送的请求字符串
</span><span >///</span> <span ></summary></span>
<span >///</span> <span ><param name="strs"></param></span>
<span >///</span> <span ><returns></returns></span>
<span >static</span> Dictionary<<span >string</span>, <span >string</span>> ParameterHandle(<span >string</span><span >[] strs)
{
Dictionary</span><<span >string</span>, <span >string</span>> param = <span >new</span> Dictionary<<span >string</span>, <span >string</span>><span >();
</span><span >if</span> (strs.Length > <span >0</span>) <span >//</span><span >解析出请求路径、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 >static</span> <span >byte</span>[] pageHandle(<span >string</span><span > pagePath)
{
</span><span >byte</span>[] pageContent = <span >null</span><span >;
webRoot </span>= webRoot.TrimEnd(<span >'</span><span >/</span><span >'</span>, <span >'</span><span >\\</span><span >'</span><span >);
pagePath </span>= pagePath.TrimEnd(<span >'</span><span >/</span><span >'</span>, <span >'</span><span >\\</span><span >'</span><span >);
</span><span >if</span> (pagePath.Length==<span >0</span><span >)
{
</span><span >foreach</span> (<span >string</span> page <span >in</span> defaultPage.Split(<span >'</span><span >,</span><span >'</span><span >))
{
</span><span >if</span> (System.IO.File.Exists(webRoot +<span > page))
{
pagePath </span>=<span > page;
</span><span >break</span><span >;
}
}
}
</span><span >if</span> (System.IO.File.Exists(webRoot +<span > pagePath))
pageContent </span>= System.IO.File.ReadAllBytes(webRoot +<span > pagePath);
</span><span >if</span> (pageContent == <span >null</span><span >)
{
</span><span >string</span> content =<span > notExistPage();
pageContent </span>=<span > Encoding.UTF8.GetBytes(content);
}
</span><span >return</span><span > pageContent;
}
</span><span >static</span> <span >void</span> writeLog(<span >string</span><span > msg)
{
Console.WriteLine(</span><span >"</span> <span >"</span> +<span > msg);
}
</span><span >static</span> <span >string</span><span > notExistPage()
{
</span><span >string</span> cont = <span >@"</span><span ><!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 class='mainContent'>
<div class='title'>This page can&rsquo;t be displayed</div>
<div class='taskSection' >
<ul class='tasks'>
<li >Make sure the web address <span class='webpageURL'></span>is correct.</li>
<li >Look for the page with your search engine.</li>
<li >Refresh the page in a few minutes.</li>
</ul>
<ul class='tasks' >
<li >Check that all network cables are plugged in.</li>
<li >Verify that airplane mode is turned off.</li>
<li >Make sure your wireless switch is turned on.</li>
<li >See if you can connect to mobile broadband.</li>
<li >Restart your router.</li>
</ul>
</div>
<div><button class='diagnoseButton' onclick='javascript:diagnoseConnectionAndRefresh(); return false;'>Fix connection problems</button></div>
</div>
</body>
</html>";
</span><span >return</span><span > 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
最近有个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:\Users\jack\Desktop</span>";
static string defaultPage = "index.html,home.html";
</span><span >static</span> <span >void</span> Main(<span >string</span><span >[] args)
{
webRoot </span>= <span >@"</span><span >C:\_jack\DevCode</span><span >"</span><span >;
_socket.Bind(</span><span >new</span> IPEndPoint(IPAddress.Any, <span >8080</span><span >));
_socket.Listen(</span><span >100</span><span >);
_socket.BeginAccept(</span><span >new</span> AsyncCallback(OnAccept), _socket); <span >//</span><span >开始接收来自浏览器的http请求(其实是socket连接请求)</span>
writeLog(<span >"</span><span >Socket Web Server 已启动监听!</span><span >"</span> + Environment.NewLine + <span >"</span><span > 监听端口:</span><span >"</span> +<span > ((IPEndPoint)_socket.LocalEndPoint).Port);
Console.ReadKey();
}
</span><span >///</span> <span ><summary></span>
<span >///</span><span > 接受处理http的请求
</span><span >///</span> <span ></summary></span>
<span >///</span> <span ><param name="ar"></param></span>
<span >static</span> <span >void</span><span > OnAccept(IAsyncResult ar)
{
</span><span >try</span><span >
{
Socket socket </span>= ar.AsyncState <span >as</span><span > Socket;
Socket web_client </span>= socket.EndAccept(ar); <span >//</span><span >接收到来自浏览器的代理socket
</span><span >//</span><span >NO.1 并行处理http请求</span>
socket.BeginAccept(<span >new</span> AsyncCallback(OnAccept), socket); <span >//</span><span >开始下一次http请求接收 (此行代码放在NO.2处时,就是串行处理http请求,前一次处理过程会阻塞下一次请求处理)</span>
<span >byte</span>[] recv_Buffer = <span >new</span> <span >byte</span>[<span >1024</span> * <span >640</span><span >];
</span><span >int</span> recv_Count = web_client.Receive(recv_Buffer); <span >//</span><span >接收浏览器的请求数据</span>
<span >string</span> recv_request = Encoding.UTF8.GetString(recv_Buffer, <span >0</span><span >, recv_Count);
writeLog(</span><span >"</span><span >Data Request : </span><span >"</span> + recv_request); <span >//</span><span >将请求显示到界面
</span><span >//</span><span >Resolve(recv_request, web_client); </span><span >//</span><span >解析、路由、处理</span>
<span >byte</span>[] cont =<span > pageHandle(RouteHandle(recv_request));
sendPageContent(cont, web_client);
</span><span >//</span><span >NO.2 串行处理http请求</span>
}
catch (Exception ex)
{
writeLog("处理http请求时出现异常!" + Environment.NewLine + "\t" + ex.Message);
}
}
</span><span >static</span> <span >void</span> sendPageContent(<span >byte</span><span >[] pageContent, Socket response)
{
</span><span >string</span> statusline = <span >"</span><span >HTTP/1.1 200 OK\r\n</span><span >"</span>; <span >//</span><span >状态行</span>
<span >byte</span>[] statusline_to_bytes =<span > Encoding.UTF8.GetBytes(statusline);
</span><span >string</span> content =
<span >"</span><span ><html></span><span >"</span> +
<span >"</span><span ><head></span><span >"</span> +
<span >"</span><span ><title>socket webServer -- Login</title></span><span >"</span> +
<span >"</span><span ></head></span><span >"</span> +
<span >"</span><span ><body></span><span >"</span> +
<span >"</span><span ><div text-align:center\"></span><span >"</span> +
<span >"</span><span >欢迎您!</span><span >"</span> + <span >""</span> + <span >"</span><span >,今天是 </span><span >"</span> + DateTime.Now.ToLongDateString() +
<span >"</span><span ></div></span><span >"</span> +
<span >"</span><span ></body></span><span >"</span> +
<span >"</span><span ></html></span><span >"</span>; <span >//</span><span >内容</span>
<span >byte</span>[] content_to_bytes =<span > pageContent;
</span><span >string</span> header = <span >string</span>.Format(<span >"</span><span >Content-Type:text/html;charset=UTF-8\r\nContent-Length:{0}\r\n</span><span >"</span><span >, content_to_bytes.Length);
</span><span >byte</span>[] header_to_bytes = Encoding.UTF8.GetBytes(header); <span >//</span><span >应答头</span>
response.Send(statusline_to_bytes); </span><span >//</span><span >发送状态行</span>
response.Send(header_to_bytes); <span >//</span><span >发送应答头</span>
response.Send(<span >new</span> <span >byte</span>[] { (<span >byte</span>)<span >'</span><span >\r</span><span >'</span>, (<span >byte</span>)<span >'</span><span >\n</span><span >'</span> }); <span >//</span><span >发送空行</span>
response.Send(content_to_bytes); <span >//</span><span >发送正文(html)</span>
response.Close();
}
</span><span >///</span> <span ><summary></span>
<span >///</span>
<span >///</span> <span ></summary></span>
<span >///</span> <span ><param name="request"></param></span>
<span >///</span> <span ><returns></returns></span>
<span >static</span> <span >string</span> RouteHandle(<span >string</span><span > request)
{
</span><span >string</span> retRoute = <span >""</span><span >;
</span><span >string</span>[] strs = request.Split(<span >new</span> <span >string</span>[] { <span >"</span><span >\r\n</span><span >"</span> }, StringSplitOptions.None); <span >//</span><span >以“换行”作为切分标志</span>
<span >if</span> (strs.Length > <span >0</span>) <span >//</span><span >解析出请求路径、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 >return</span><span > retRoute;
}
</span><span >///</span> <span ><summary></span>
<span >///</span><span > 按照HTTP协议格式,解析浏览器发送的请求字符串
</span><span >///</span> <span ></summary></span>
<span >///</span> <span ><param name="strs"></param></span>
<span >///</span> <span ><returns></returns></span>
<span >static</span> Dictionary<<span >string</span>, <span >string</span>> ParameterHandle(<span >string</span><span >[] strs)
{
Dictionary</span><<span >string</span>, <span >string</span>> param = <span >new</span> Dictionary<<span >string</span>, <span >string</span>><span >();
</span><span >if</span> (strs.Length > <span >0</span>) <span >//</span><span >解析出请求路径、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 >static</span> <span >byte</span>[] pageHandle(<span >string</span><span > pagePath)
{
</span><span >byte</span>[] pageContent = <span >null</span><span >;
webRoot </span>= webRoot.TrimEnd(<span >'</span><span >/</span><span >'</span>, <span >'</span><span >\\</span><span >'</span><span >);
pagePath </span>= pagePath.TrimEnd(<span >'</span><span >/</span><span >'</span>, <span >'</span><span >\\</span><span >'</span><span >);
</span><span >if</span> (pagePath.Length==<span >0</span><span >)
{
</span><span >foreach</span> (<span >string</span> page <span >in</span> defaultPage.Split(<span >'</span><span >,</span><span >'</span><span >))
{
</span><span >if</span> (System.IO.File.Exists(webRoot +<span > page))
{
pagePath </span>=<span > page;
</span><span >break</span><span >;
}
}
}
</span><span >if</span> (System.IO.File.Exists(webRoot +<span > pagePath))
pageContent </span>= System.IO.File.ReadAllBytes(webRoot +<span > pagePath);
</span><span >if</span> (pageContent == <span >null</span><span >)
{
</span><span >string</span> content =<span > notExistPage();
pageContent </span>=<span > Encoding.UTF8.GetBytes(content);
}
</span><span >return</span><span > pageContent;
}
</span><span >static</span> <span >void</span> writeLog(<span >string</span><span > msg)
{
Console.WriteLine(</span><span >"</span> <span >"</span> +<span > msg);
}
</span><span >static</span> <span >string</span><span > notExistPage()
{
</span><span >string</span> cont = <span >@"</span><span ><!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 class='mainContent'>
<div class='title'>This page can&rsquo;t be displayed</div>
<div class='taskSection' >
<ul class='tasks'>
<li >Make sure the web address <span class='webpageURL'></span>is correct.</li>
<li >Look for the page with your search engine.</li>
<li >Refresh the page in a few minutes.</li>
</ul>
<ul class='tasks' >
<li >Check that all network cables are plugged in.</li>
<li >Verify that airplane mode is turned off.</li>
<li >Make sure your wireless switch is turned on.</li>
<li >See if you can connect to mobile broadband.</li>
<li >Restart your router.</li>
</ul>
</div>
<div><button class='diagnoseButton' onclick='javascript:diagnoseConnectionAndRefresh(); return false;'>Fix connection problems</button></div>
</div>
</body>
</html>";
</span><span >return</span><span > 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