C#自制Web 服务器开发:用C#开发自己的Web服务器

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
View Code

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

以上的  %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 + "\r\n";

            sBuffer = sBuffer + "Server: cx1193719-b\r\n";

            sBuffer = sBuffer + "Content-Type: " + sMIMEHeader + "\r\n";

            sBuffer = sBuffer + "Accept-Ranges: bytes\r\n";

            sBuffer = sBuffer + "Content-Length: " + iTotBytes + "\r\n\r\n";

            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("\nClient Connected!!\n==================\nCLient IP {0}\n", 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();

        }

 

 

 

你可能感兴趣的:(web服务器)