zoukankan      html  css  js  c++  java
  • C#中使用Socket实现简单Web服务器

    原文地址:https://www.cnblogs.com/mq0036/p/6656888.html

    最近有个web的小项目,但公司的电脑无法安装IIS,所以就想自己来实现个Web server服务器,原本想了下,也就是socket处理http请求,于是就在博客园中搜索了“socket实现web server”,结果还真搜索到一些文章,于是从中找了几个做参考,如下:

    C#中使用Socket实现简单Web服务器

    C#中使用Socket模拟请求Web服务器过程

    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;">&lt;summary&gt;</span>
        <span style="color: #808080;">///</span><span style="color: #008000;"> 接受处理http的请求
        </span><span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span>
        <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;param name="ar"&gt;&lt;/param&gt;</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;">&lt;html&gt;</span><span style="color: #800000;">"</span> +
                <span style="color: #800000;">"</span><span style="color: #800000;">&lt;head&gt;</span><span style="color: #800000;">"</span> +
                    <span style="color: #800000;">"</span><span style="color: #800000;">&lt;title&gt;socket webServer  -- Login&lt;/title&gt;</span><span style="color: #800000;">"</span> +
                <span style="color: #800000;">"</span><span style="color: #800000;">&lt;/head&gt;</span><span style="color: #800000;">"</span> +
                <span style="color: #800000;">"</span><span style="color: #800000;">&lt;body&gt;</span><span style="color: #800000;">"</span> +
                   <span style="color: #800000;">"</span><span style="color: #800000;">&lt;div style="text-align:center"&gt;</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;">&lt;/div&gt;</span><span style="color: #800000;">"</span> +
                <span style="color: #800000;">"</span><span style="color: #800000;">&lt;/body&gt;</span><span style="color: #800000;">"</span> +
            <span style="color: #800000;">"</span><span style="color: #800000;">&lt;/html&gt;</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.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>
    
    response.Close();
        }
    
        </span><span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span>
        <span style="color: #808080;">///</span> 
        <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span>
        <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;param name="request"&gt;&lt;/param&gt;</span>
        <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;returns&gt;&lt;/returns&gt;</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 &gt; <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;">&lt;summary&gt;</span>
        <span style="color: #808080;">///</span><span style="color: #008000;"> 按照HTTP协议格式,解析浏览器发送的请求字符串
        </span><span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span>
        <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;param name="strs"&gt;&lt;/param&gt;</span>
        <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;returns&gt;&lt;/returns&gt;</span>
        <span style="color: #0000ff;">static</span> Dictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">string</span>&gt; ParameterHandle(<span style="color: #0000ff;">string</span><span style="color: #000000;">[] strs)
        {
            Dictionary</span>&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">string</span>&gt; param = <span style="color: #0000ff;">new</span> Dictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">string</span>&gt;<span style="color: #000000;">();
    
            </span><span style="color: #0000ff;">if</span> (strs.Length &gt; <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;">&lt;!DOCTYPE HTML&gt;
    

    <html>

    &lt;head&gt;
        &lt;link rel='stylesheet' type='text/css' href='NewErrorPageTemplate.css' &gt;
    
        &lt;meta http-equiv='Content-Type' content='text/html; charset=UTF-8'&gt;
        &lt;title&gt;This page can&amp;rsquo;t be displayed&lt;/title&gt;
    
        &lt;script src='errorPageStrings.js' language='javascript' type='text/javascript'&gt;
        &lt;/script&gt;
        &lt;script src='httpErrorPagesScripts.js' language='javascript' type='text/javascript'&gt;
        &lt;/script&gt;
    &lt;/head&gt;
    
    &lt;body onLoad='javascript:getInfo();'&gt;
        &lt;div id='contentContainer' class='mainContent'&gt;
            &lt;div id='mainTitle' class='title'&gt;This page can&amp;rsquo;t be displayed&lt;/div&gt;
            &lt;div class='taskSection' id='taskSection'&gt;
                &lt;ul id='cantDisplayTasks' class='tasks'&gt;
                    &lt;li id='task1-1'&gt;Make sure the web address &lt;span id='webpage' class='webpageURL'&gt;&lt;/span&gt;is correct.&lt;/li&gt;
                    &lt;li id='task1-2'&gt;Look for the page with your search engine.&lt;/li&gt;
                    &lt;li id='task1-3'&gt;Refresh the page in a few minutes.&lt;/li&gt;
                &lt;/ul&gt;
                &lt;ul id='notConnectedTasks' class='tasks' style='display:none'&gt;
                    &lt;li id='task2-1'&gt;Check that all network cables are plugged in.&lt;/li&gt;
                    &lt;li id='task2-2'&gt;Verify that airplane mode is turned off.&lt;/li&gt;
                    &lt;li id='task2-3'&gt;Make sure your wireless switch is turned on.&lt;/li&gt;
                    &lt;li id='task2-4'&gt;See if you can connect to mobile broadband.&lt;/li&gt;
                    &lt;li id='task2-5'&gt;Restart your router.&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
            &lt;div&gt;&lt;button id='diagnose' class='diagnoseButton' onclick='javascript:diagnoseConnectionAndRefresh(); return false;'&gt;Fix connection problems&lt;/button&gt;&lt;/div&gt;
        &lt;/div&gt;
    &lt;/body&gt;
    

    </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

  • 相关阅读:
    Linux基础知识整理
    小白学习之路,基础四(函数的进阶)
    关于高通量数据格式
    数据库管理系统
    Linux 基本操作
    生信研究内容
    redis6 多线程特性
    Centos8配置NFS4
    关于Mybatis将查询结果中添加常量列并返回
    关于swagger文档的使用方法
  • 原文地址:https://www.cnblogs.com/dawenxi0/p/11584133.html
Copyright © 2011-2022 走看看