C#模拟IIS服务器(一)

    xiaoxiao2021-03-25  110

    为了更加透彻理解 IIS 服务器原理,自己简单模拟了IIS服务器工作原理,事实证明确实有助于理解!

    using System;

    using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 小型IIS服务器 {     using System.Net.Sockets;     using System.Net;     /// <summary>     /// 负责网站socket的监听     /// </summary>     public class IISWebServer     {         #region 1.0 定义变量         //定义服务器端监听socket         Socket serverSocket;         //服务器IP地址         string ip;         //服务器端口号         int port;         //定义action泛型委托 传递一个方法进来 为txtRequestStr赋值 将客户端请求报文 显示出来         Action<string> displayMsg;         //是否继续循环 用于监听和响应         bool isStop = false;         #endregion         #region 2.0 构造函数实例化 ip port 传进方法 给txtRequestStr赋值         /// <summary>         /// 无参构造方法         /// </summary>         public IISWebServer() { }         /// <summary>         /// 有参构造方法         /// </summary>         /// <param name="ip"></param>         /// <param name="port"></param>         /// <param name="displayMsg"></param>         public IISWebServer(string ip, int port, Action<string> displayMsg)         {             this.ip = ip;             this.port = port;             this.displayMsg = displayMsg;         }         #endregion         #region 3.0 启动IIS服务器的方法 入口 在Form1 btnStart_Click 方法中被调用         /// <summary>         /// 启动IIS服务器         /// </summary>         public void Start()         {             //01 实例化一个流式套接口             //使用IP4 IP地址 Stream流式套接口 TCP协议             serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);             //02 给套接口绑定ip port             //IPEndPoint 将网络端点表示为 ip地址 和 端口号             //IPAddress 提供网际协议(IP)地址             //IPAddress.Parse(string ip) 让IP地址字符串转换为system.Net.IPAddress实例             //IPEndPoint(IPAddress.Parse(ip),port) 用指定的IP port 初始化system.Net.IPEndPoint的新实例             IPEndPoint ipp = new IPEndPoint(IPAddress.Parse(ip), port);             serverSocket.Bind(ipp);             //03 打开监听             serverSocket.Listen(20);             //04 开启线程等待浏览器的请求 由于AcceptCilent()会阻断主线程 所以开启子线程来接收客户端链接             System.Threading.Thread th = new System.Threading.Thread(AcceptCilent);             th.IsBackground = true;     //该线程是否为后台线程             th.Start();         }         #endregion         #region 4.0 等待浏览器向服务器请求         /// <summary>         /// 等待浏览器向服务器请求         /// </summary>         private void AcceptCilent()         {             while (!isStop)             {                 try                 {                     //开启服务器之后 代码执行到这就会停止 等待用户连接 一旦连接 就继续往下执行                     //01 浏览器已发出请求 就会触发Accept()方法                     Socket cSocket = serverSocket.Accept();                     //02 监听到浏览器发出请求后 定义一个子线程 用来接收请求报文                      //子线程 因为ReceiveCilent()方法会阻断主线程 所以开辟子线程实现接收用户请求报文                     //当前线程只负责与当前浏览器通信                        //System.Threading.ParameterizedThreadStart(ReceiveCilent) ReceiveCilent在线程上执行的方法                     System.Threading.Thread thReceive = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(ReceiveCilent));                     thReceive.IsBackground = true;                     //开启线程时将当前的cSocket传给ReceiveCilent  因为每个线程的cSocket不一样                     thReceive.Start(cSocket);                 }                 catch { }                             }         }         #endregion         #region 5.0 接收浏览器的请求报文  在第4.0步被调用         /// <summary>         /// 接收浏览器的请求报文         /// </summary>         private void ReceiveCilent(object cSocket)         {             //因为每次浏览器向服务器请求时 cSocket不同,所以要转换为Socket型             //当前线程只负责和当前浏览器通信 每个线程都会传一个cSocket进来 每个线程的cSocket不一样 所以tmpSocket所存储的变量不同              //所以在这里要转型             Socket tmpSocket = cSocket as Socket;             //申请1M的空间来存储请求报文信息             byte[] receiveBuffer = new byte[1024 * 1024];             string requestString = string.Empty;             while (!isStop)             {                 try                 {                     //代码执行到这也会停止 等待用户的请求报文                      int len = tmpSocket.Receive(receiveBuffer);                     //接收浏览器请求报文数据                     //1.0 将请求报文数据转换为字符串赋值给requestString                     requestString = System.Text.Encoding.UTF8.GetString(receiveBuffer, 0, len);                     //tmpSocket.Receive(receiveBuffer);                     //2.0 将浏览器请求报文在txtReceiveStr中显示                     displayMsg(requestString);                     //3.0 将请求报文送往ASP.NET框架处理机制                     byte[] responseByte = IsApiRuntime.ProcessRequest(requestString);                     //4.0 通过浏览器的连接套接字tmpSocket 的Send方法将响应报文数据反馈给浏览器                     tmpSocket.Send(responseByte);                 }                 catch                 {                 }             }         }         #endregion     } }
    转载请注明原文地址: https://ju.6miu.com/read-7570.html

    最新回复(0)