• (转)C#自制Web 服务器开发:用C#开发自己的Web服务器


    复制代码
    当输入:127.0.0.1:5050
    
    GET / HTTP/1.1
    Accept: text/html, application/xhtml+xml, */*
    Accept-Language: zh-CN
    User-Agent: Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko
    Accept-Encoding: gzip, deflate
    Host: 127.0.0.1:5050
    DNT: 1
    Connection: Keep-Alive
    Cookie: s_pers=%20s_fid%3D5E4387B367FCC613-0DC7FD9C6D76C087%7C1453856077838%3B%20s_vs%3D1%7C1390785877860%3B%20s_nr%3D1390784077867-New%7C1422320077867%3B
    
    
    
    http://127.0.0.1:5050/index.html
    
    GET /index.html HTTP/1.1
    Accept: text/html, application/xhtml+xml, */*
    Accept-Language: zh-CN
    User-Agent: Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko
    Accept-Encoding: gzip, deflate
    Host: 127.0.0.1:5050
    DNT: 1
    Connection: Keep-Alive
    Cookie: s_pers=%20s_fid%3D5E4387B367FCC613-0DC7FD9C6D76C087%7C1453856077838%3B%20s_vs%3D1%7C1390785877860%3B%20s_nr%3D1390784077867-New%7C1422320077867%3B
    
    
    提交表单
    
    POST / HTTP/1.1
    Host: 127.0.0.1:5050
    User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:27.0) Gecko/20100101 Firefox/27.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    DNT: 1
    Cookie: s_pers=%20s_fid%3D5E4387B367FCC613-0DC7FD9C6D76C087%7C1453856077838%3B%20s_vs%3D1%7C1390785877860%3B%20s_nr%3D1390784077867-New%7C1422320077867%3B
    Connection: keep-alive
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 51
    
    txtName=&txtClass=&txtPassword=&Submit=%CC%E1%BD%BB
    
    
    提交表单 2
    
    POST /CCC.asp HTTP/1.1
    Host: 127.0.0.1:5050
    User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:27.0) Gecko/20100101 Firefox/27.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    DNT: 1
    Cookie: s_pers=%20s_fid%3D5E4387B367FCC613-0DC7FD9C6D76C087%7C1453856077838%3B%20s_vs%3D1%7C1390785877860%3B%20s_nr%3D1390784077867-New%7C1422320077867%3B
    Connection: keep-alive
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 68
    
    txtName=name&txtClass=class&txtPassword=password&Submit=%CC%E1%BD%BB
    
    
    提交表单3
    POST /CCC.asp HTTP/1.1
    Host: 127.0.0.1:5050
    User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:27.0) Gecko/20100101 Firefox/27.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    DNT: 1
    Cookie: s_pers=%20s_fid%3D5E4387B367FCC613-0DC7FD9C6D76C087%7C1453856077838%3B%20s_vs%3D1%7C1390785877860%3B%20s_nr%3D1390784077867-New%7C1422320077867%3B
    Connection: keep-alive
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 93
    
    txtName=%D5%C5%C8%FD&txtClass=%B8%DF%D2%BB%B6%FE%B0%E0&txtPassword=990749&Submit=%CC%E1%BD%BB
    复制代码

    以上是 浏览器在浏览时发送给服务器的数据内容.在不同情况下会有所不同.不过,一般数据量都很小.

    以上的  %D5%C5%C8%FD  实际上是 urlencode 编码方式:在程序开发的过程,需要对其进行解码

    由于IIS的不稳定性和难实施性(对操作系统太挑剔),一直想做个自己的轻量级Web服务器。

    今天终于抽出时间,借助网络上的实例,实现了自己的服务器,计划以后在项目开发时尝试取代IIS服务器。

    在此把整体实现过程记录下,以备后用。

    技术实现原理:

    1.需要了解HTTP的工作原理

    2.需要了解基于C#的SOCKET编程,TcpListener类对象,监听端口

    一、启动VS2005,新建一个控制台程序,命名:ConsoleApplication1

    二、在添加CS文件,使名:MyWebServer.cs

    三、实现类MyWebServer,代码如下:

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    
    namespace WindowsFormsApplication1
    {
        class MyWebServer
        {
            private TcpListener myListener;
            private int port = 8899; // 选者任何闲置端口
            //开始兼听端口
            //同时启动一个兼听进程
            public MyWebServer()
            {
                try
                {
                    //开始兼听端口
                    myListener = new TcpListener(port);
                    myListener.Start();
                    Console.WriteLine("Web Server Running... Press ^C to Stop...");
                    //同时启动一个兼听进程 ''StartListen''
                    Thread th = new Thread(new ThreadStart(StartListen));
                    th.Start();
                }
                catch (Exception e)
                {
                    Console.WriteLine("兼听端口时发生错误 :" + e.ToString());
                }
            }
            public void SendHeader(string sHttpVersion, string sMIMEHeader, int iTotBytes, string sStatusCode, ref Socket mySocket)
            {
    
                String sBuffer = "";
                if (sMIMEHeader.Length == 0)
                {
                    sMIMEHeader = "text/html"; // 默认 text/html
                }
                sBuffer = sBuffer + sHttpVersion + sStatusCode + "
    ";
                sBuffer = sBuffer + "Server: cx1193719-b
    ";
                sBuffer = sBuffer + "Content-Type: " + sMIMEHeader + "
    ";
                sBuffer = sBuffer + "Accept-Ranges: bytes
    ";
                sBuffer = sBuffer + "Content-Length: " + iTotBytes + "
    
    ";
                Byte[] bSendData = Encoding.ASCII.GetBytes(sBuffer);
                SendToBrowser(bSendData, ref mySocket);
                Console.WriteLine("Total Bytes : " + iTotBytes.ToString());
            }
            public void SendToBrowser(String sData, ref Socket mySocket)
            {
                SendToBrowser(Encoding.ASCII.GetBytes(sData), ref mySocket);
            }
    
            public void SendToBrowser(Byte[] bSendData, ref Socket mySocket)
            {
                int numBytes = 0;
    
                try
                {
                    if (mySocket.Connected)
                    {
                        if ((numBytes = mySocket.Send(bSendData, bSendData.Length, 0)) == -1)
                            Console.WriteLine("Socket Error cannot Send Packet");
                        else
                        {
                            Console.WriteLine("No. of bytes send {0}", numBytes);
                        }
                    }
                    else
                        Console.WriteLine("连接失败....");
                }
                catch (Exception e)
                {
                    Console.WriteLine("发生错误 : {0} ", e);
    
                }
            }
            public void StartListen()
            {
    
                int iStartPos = 0;
                String sRequest;
                String sDirName;
                String sRequestedFile;
                String sErrorMessage;
                String sLocalDir;
                /////////////////////////////////////注意设定你自己的虚拟目录/////////////////////////////////////
                String sMyWebServerRoot = "C:\Cassini"; //设置你的虚拟目录
                //////////////////////////
                String sFormattedMessage = "";
                String sResponse = "";
    
    
                while (true)
                {
                    //接受新连接
                    Socket mySocket = myListener.AcceptSocket();
    
                    Console.WriteLine("Socket Type " + mySocket.SocketType);
                    if (mySocket.Connected)
                    {
                        Console.WriteLine("
    Client Connected!!
    ==================
    CLient IP {0}
    ", mySocket.RemoteEndPoint);
    
                        Byte[] bReceive = new Byte[1024];
                        int i = mySocket.Receive(bReceive, bReceive.Length, 0);
    
    
                        //转换成字符串类型
                        string sBuffer = Encoding.ASCII.GetString(bReceive);
    
    
                        //只处理"get"请求类型
                        if (sBuffer.Substring(0, 3) != "GET")
                        {
                            Console.WriteLine("只处理get请求类型..");
                            mySocket.Close();
                            return;
                        }
    
                        // 查找 "HTTP" 的位置
                        iStartPos = sBuffer.IndexOf("HTTP", 1);
    
    
                        string sHttpVersion = sBuffer.Substring(iStartPos, 8);
    
    
                        // 得到请求类型和文件目录文件名
                        sRequest = sBuffer.Substring(0, iStartPos - 1);
    
                        sRequest.Replace("", "/");
    
    
                        //如果结尾不是文件名也不是以"/"结尾则加"/"
                        if ((sRequest.IndexOf(".") < 1) && (!sRequest.EndsWith("/")))
                        {
                            sRequest = sRequest + "/";
                        }
    
    
                        //得带请求文件名
                        iStartPos = sRequest.LastIndexOf("/") + 1;
                        sRequestedFile = sRequest.Substring(iStartPos);
    
    
                        //得到请求文件目录
                        sDirName = sRequest.Substring(sRequest.IndexOf("/"), sRequest.LastIndexOf("/") - 3);
    
    
                        //获取虚拟目录物理路径
                        sLocalDir = sMyWebServerRoot;
    
                        Console.WriteLine("请求文件目录 : " + sLocalDir);
    
                        if (sLocalDir.Length == 0)
                        {
                            sErrorMessage = "<H2>Error!! Requested Directory does not exists</H2><Br>";
                            SendHeader(sHttpVersion, "", sErrorMessage.Length, " 404 Not Found", ref mySocket);
                            SendToBrowser(sErrorMessage, ref mySocket);
                            mySocket.Close();
                            continue;
                        }
    
    
                        if (sRequestedFile.Length == 0)
                        {
                            // 取得请求文件名
                            sRequestedFile = "index.html";
                        }
    
    
                        /////////////////////////////////////////////////////////////////////
                        // 取得请求文件类型(设定为text/html)
                        /////////////////////////////////////////////////////////////////////
    
                        String sMimeType = "text/html";
    
                        string sPhysicalFilePath = sLocalDir + sRequestedFile;
                        Console.WriteLine("请求文件: " + sPhysicalFilePath);
    
    
                        if (File.Exists(sPhysicalFilePath) == false)
                        {
    
                            sErrorMessage = "<script language='javascript'>alert('你好呀,我不是IIS服务器!');</script>";
                            //SendHeader(sHttpVersion, "", sErrorMessage.Length, " 404 Not Found", ref mySocket);
                            //SendToBrowser(sErrorMessage, ref mySocket);
                            byte[] bytes = Encoding.GetEncoding("GB2312").GetBytes(sErrorMessage);
                            SendHeader(sHttpVersion, sMimeType, bytes.Length, " 200 OK", ref mySocket);
                            SendToBrowser(bytes, ref mySocket);
                            //Console.WriteLine(sFormattedMessage);
                        }
                        else
                        {
                            int iTotBytes = 0;
    
                            sResponse = "";
    
                            FileStream fs = new FileStream(sPhysicalFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
    
                            BinaryReader reader = new BinaryReader(fs);
                            byte[] bytes = new byte[fs.Length];
                            int read;
                            while ((read = reader.Read(bytes, 0, bytes.Length)) != 0)
                            {
                                sResponse = sResponse + Encoding.ASCII.GetString(bytes, 0, read);
    
                                iTotBytes = iTotBytes + read;
    
                            }
                            reader.Close();
                            fs.Close();
    
                            SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket);
                            SendToBrowser(bytes, ref mySocket);
                            //mySocket.Send(bytes, bytes.Length,0);
    
                        }
                        mySocket.Close();
                    }
                }
            }
        }
    }
    复制代码

    四、编辑Program.cs,启动监听

    复制代码
    static void Main(string[] args)
            {
                MyWebServer MWS = new MyWebServer();
                Console.Read();
            }
    复制代码
  • 相关阅读:
    UITextField的总结
    【实战】登录界面
    点分治学习
    2020/3/1
    2020/2/29
    2020/2/28
    2020/2/27
    2020/2/27
    最小树形图
    Ch’s gift HDU6162
  • 原文地址:https://www.cnblogs.com/lhuan/p/3829143.html
Copyright © 2020-2023  润新知