自定义轻量级的HTTP WebServer (WEB服务器)

一直觉得网站www.studyez.com 处理静态文件不怎么快,就想能不能把这些静态文件单独放在另外一台服务器(StaticFileServer)上面。让主服务器只处理.aspx文件即可。StaticFileServer只负责输出静态文件,减轻主服务器的压力。远景的想法是把它用C/C++改写。

不过,发现用C/C++哪是相当的麻烦,而且也没有必要。反正就是自己用用。先搭个架子先吧。

对于以后的GET请求的分析,稍后在发上来。网上找的一些基上都是把接收到byte[]转化成字符串然后来分析,

个人觉得这种做法效率不怎么好。不过目前也没想到什么好法子。特别对于POST请求的分析。

下面涉及到异步回调《AsyncCallback》,Socket 等东西。好记性不如烂笔头,还是记下先吧。

 

下面是源代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Net.Cache;
using System.IO;


namespace WinSocket
{
    public class HttpSocket
    {
        static System.Threading.AutoResetEvent a = new System.Threading.AutoResetEvent(true);
        static void Main(string[] args)
        {
            IPHostEntry en = Dns.GetHostEntry("127.0.0.1");
            IPAddress ipAddr = en.AddressList[0];

            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            server.Bind(new IPEndPoint(ipAddr, 10000));
            server.Listen(1000);
            try
            {
                while (true)
                {
                    a.Reset();
                    Console.WriteLine("Waiting for a connection...");
                    server.BeginAccept(new AsyncCallback(AcceptReceiveDataCallback), server);

                     //int receivedDataSize = 1024;
                     //server.BeginAccept(receivedDataSize, new AsyncCallback(AcceptReceiveDataCallback), server);

                   // Wait until a connection is made and processed before continuing.
                    a.WaitOne();
   
                }
            }
            finally
            {
                server.Shutdown(SocketShutdown.Both);
                server.Close();
            }

        }

        static void AcceptReceiveDataCallback(IAsyncResult ar)
        {
            // Get the socket that handles the client request.
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);
            //byte[] Buffer;
            //int bytesTransferred;
            //Socket handler = listener.EndAccept(out Buffer, out bytesTransferred, ar);
            a.Set();
            //string stringTransferred = Encoding.ASCII.GetString(Buffer, 0, bytesTransferred);
            //Console.WriteLine(stringTransferred);
            //Console.WriteLine("Size of data transferred is {0}", bytesTransferred);

            ReceiveStateObject state = new ReceiveStateObject(handler, 1024);

            handler.BeginReceive(state.Buffer, 0, state.BufferSize, SocketFlags.None,  new AsyncCallback(ReadCallback), state);
        }
        static void ReadCallback(IAsyncResult ar)
        {
       
            ReceiveStateObject state = (ReceiveStateObject)ar.AsyncState;
            Socket handler = state.WorkerSocket;
            int read = handler.EndReceive(ar);
            if (read > 0 && read ==state.BufferSize )
            {
                //继续读取
                handler.BeginReceive(state.Buffer, 0, state.BufferSize, SocketFlags.None, new AsyncCallback(ReadCallback), state);
            }
            else
            {
                //处理结束
                //读取结束
                StringBuilder _sb = new StringBuilder();
                FileInfo fi = new FileInfo(@"H:/HttpWebServer/index.html");
                _sb.AppendLine("HTTP/1.0 200 OK");
                _sb.AppendLine("MIME-version:1.0");
                _sb.AppendLine("Content-type:text/html");
                _sb.AppendLine("Content-length:" + fi.Length.ToString());
                _sb.AppendLine();
                byte[] c = System.Text.Encoding.Default.GetBytes(_sb.ToString());
                handler.BeginSend(c, 0, c.Length, SocketFlags.None, new AsyncCallback(SendCallback), new ResponseStateObject(handler, c.Length));
            }


        }
        static void SendCallback(IAsyncResult ar)
        {
            ResponseStateObject res = (ResponseStateObject)ar.AsyncState;
            Socket handler = res.WorkerSocket;
            int c = handler.EndSend(ar);
            if (c != res.Len)
            {
                Console.WriteLine("数据尚未正确发送出去!");


            }
            else
            {
                handler.BeginSendFile(@"H:/HttpWebServer/index.html", new AsyncCallback(SendFileCallback), new SendFileStateObject(handler));
            }
        }
        static void SendFileCallback(IAsyncResult ar)
        {
            SendFileStateObject st = (SendFileStateObject)ar.AsyncState;
            st.WorkerSocket.EndSendFile(ar);
            st.WorkerSocket.Shutdown(SocketShutdown.Both);
            st.WorkerSocket.Close();
        }
        class ReceiveStateObject
        {
            private Byte[] _buffer;
            private int _size;
            private Socket _s;
            private StringBuilder sb;
            public ReceiveStateObject(Socket woker, int bufferSize)
            {
                _s = woker;
                _size = bufferSize;
                _buffer = new byte[bufferSize];
                sb = new StringBuilder();

            }
            public Socket WorkerSocket
            {
                get { return _s; }
            }

            public int BufferSize
            {
                get { return _size; }
            }
            public Byte[] Buffer
            {
                get { return _buffer; }
            }
            public StringBuilder ContentContainer
            {
                get { return sb; }
            }
        }
        class ResponseStateObject
        {
            public int Len;
            public Socket WorkerSocket;
            public ResponseStateObject(Socket s, int sendLen)
            {
                WorkerSocket = s;
                Len = sendLen;
            }
        }
        class SendStateObject
        {
            private Byte[] _buffer;

            private Socket _s;
            public SendStateObject(Socket socket, byte[] buffer)
            {
                _s = socket;
                _buffer = buffer;

            }
            public Socket WorkerSocket
            {
                get { return _s; }
            }


            public Byte[] Buffer
            {
                get { return _buffer; }
            }
        }

        class SendFileStateObject
        {
            public Socket WorkerSocket;

            public SendFileStateObject(Socket s)
            {
                WorkerSocket = s;
            }
        }

    }
}

MyWebServer v3.1.29更新日志: 增加实时流量查看,完善NT服务功能,增加静默启动(加/s命令行启动时不显示主窗口),优化一些网络参数 MyWebServer是一个高性能、易用、小巧、绿色的轻量级WEB服务器软件,是你快速建站及个人HTTP文件服务器的难得工具。支持HTTP/1.1、断点续传、大文件下载、正则表达式URL重写、虚拟目录、HTTP反向代理等,可通过ISAPI接口、FastCGI接口实现执行服务器脚本(如PHP,asp,asp.net等),性能完全超越IIS等很多主流WEB服务器软件。   MyWebServer使用说明: 使用FastCGI时,在映射设置中将映射模块设置为启动FastCGI的命令,且命令行中必须包含IP:port格式(如:127.0.0.1:8988)的服务器信息,当不需要WEB服务器启动FastCGI时,命令行中填入IP:port格式的FastCGI服务器信息即可。 如果使用ISAPI接口,指定ISAPI的DLL文件即可。   注(本服务器不集成任何动态脚本支持,要使用请自行安装):asp支持可安装IASP(该软件要求安装java运行环境)通过isapi接口实现;PHP通过isapi和FastCGI接口均可(isapi方式建议使用PHP 5.2,因为5.3以上版不再提供ISAPI支持);asp.net支持可安装mono然后通过FasctCGI接口实现。上述脚本已测试过可以运行。   URL重写命令(使用基于VBScript的正则表达式): ifsve  如果匹配指定的服务器变量则往下执行,否则执行下条exitr之后的规则。(目前仅支持HTTP_HOST REMOTE_ADDR HTTP_REFERER三个服务器变量) ifurl  如果匹配请求的URL则执行wrurl重写命令,否则执行下条exitr之后的规则。 wrurl  执行URL重写 exitr  结束url重写,不再往下执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值