Web服务器具体开发流程

下面是我个人对Web服务器开发流程的一点理解,下面做出了大概的模型,实现了基本的功能,下面也有所有的代码可以提供参考;

一开始学的时候不要把网站想的太复杂了,把网站的流程和大概的原理框架搞清楚,在通过代码大概的实现出来,这样以后面对网站开发的时候就会有一个具体的模型。

网站是一种通讯工具,就像布告栏一样,人们可以通过网站来发布自己想要公开的资讯,或者利用网站来提供相关的网络服务。人们可以通过网页浏览器来访问网站,获取自己需要的资讯或者享受网络服务。

其实Web服务器网站开发无非就是接收到客户端发送过来的请求页面,然后对报文进行有必要的处理,在这个过程可以用事件管道处理来提高扩展性,在重新组装成新的报文,把它按照指定的报文格式发送回客户端去,而浏览器就可以得到响应,接收到想要的数据页面,同时,网站服务将关闭,等有新的请求的时候在开启服务。这个是客户端请求网站数据时的大概过程。

代码都有详细的注释,我就不多列外写了。

当然,这只是我个人的一点理解,我也是初学者,所以仅供参考,有不对的地方也可以指出。

forMyServer网站主页

 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Data;
 using System.Drawing;
 using System.IO;
 using System.Linq;
 using System.Net;
 using System.Net.Sockets;
 using System.Runtime.Serialization.Formatters.Binary;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Windows.Forms;

 namespace MyServer
 {
     public partial class forMyServer : Form
     {
         public forMyServer()
         {
             InitializeComponent();
         }
         private Sites sites = null;//站点实体
         BinaryFormatter formatter = null;//序列化
         private void menuAdd_Click(object sender, EventArgs e)
         {
             forAddServer f = new forAddServer();
             f.SiteEvent += ServerSite;//添加事件
             f.ShowDialog();
         }
         private void ServerSite(Site s)//事件处理
         {
             treeView1.Nodes.Clear();
             sites.Add(s);
             string fileName = "a.dat";//序列化文件名(随便取的)
             string path = Application.ExecutablePath;//获取路劲
             path = path.Substring(, path.LastIndexOf('\\'));
             fileName = path + "\\" + fileName;//带路径的文件名
             using (FileStream fs = new FileStream(fileName, FileMode.Create))
             {
                 formatter = new BinaryFormatter();
                 formatter.Serialize(fs, sites);//序列化对象
             }
             TreeNode root = new TreeNode("所有站点");
             treeView1.Nodes.Add(root);
             foreach(Site site in sites)//添加站点到属性控件
             {
                 TreeNode node = new TreeNode(site.SiteName);
                 node.Tag = site;
                 root.Nodes.Add(node);
             }
         }

         private void forMyServer_Load(object sender, EventArgs e)
         {
             string fileName = "a.dat";
             string path = Application.ExecutablePath;
             path = path.Substring(, path.LastIndexOf('\\'));
             fileName = path + "\\" + fileName;
             sites = new Sites();
             if (!File.Exists(fileName))
                 File.Create(fileName);
             using (FileStream fs = new FileStream(fileName, FileMode.Open))
             {
                 if (sites != null)
                 {
                     formatter = new BinaryFormatter();
                     sites = formatter.Deserialize(fs) as Sites;
                     TreeNode root = new TreeNode("所有站点");
                     treeView1.Nodes.Add(root);
                     foreach (Site s in sites)
                     {
                         TreeNode node = new TreeNode(s.SiteName);
                         node.Tag = s;
                         root.Nodes.Add(node);
                     }
                 }
             }
         }

         private void menuStart_Click(object sender, EventArgs e)
         {
             //取出树形控件中选中的站点
             )
             {
                 //取出用户选中的站点对象
                 Site currSite = treeView1.SelectedNode.Tag as Site;
                 //站点没有开启就开启
                 if (!currSite.IsStart)
                 {
                     ParameterizedThreadStart p = new ParameterizedThreadStart(ListenSocket);
                     Thread t1 = new Thread(p);
                     t1.Start(currSite);//开启一个线程
                 }
             }
         }
         public void ListenSocket(object currSite) //监听Ip地址
         {
             Site s = currSite as Site;
             Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
             EndPoint endPoint = );
             server.Bind(endPoint);
             server.Listen();//开启监听
             s.IsStart = true;//表示以开启此站点,不用开启
             HttpContext h = new HttpContext();
             h.SitePath = s.Path;
             while(true)
             {
                 Socket client = server.Accept();//接收用户实例
                 h.TxSocket = client;
                 Thread t = new Thread(Process);
                 t.Start(h);
             }
         }
         public void Process(object c)//发送页面回去的处理流程
         {
             HttpContext h = c as HttpContext;
             Socket client = h.TxSocket;
             ];
             int length = client.Receive(b);
             , length);//得到报文
             h.Info = new HttpInfo(str);//拆分报文
             h.Response = new HttpResponse();//组装新的报文
             HttpAllContext allContext = new HttpAllContext();//所有信息
             h.Context = allContext;
             HttpFactory.CreateHandler(h);
             allContext.ProcessPage(h);//触发事件
             client.Send(h.Response.b);//发送数据
             client.Close();//关闭服务
         }

         private void 退出服务ToolStripMenuItem_Click(object sender, EventArgs e)
         {
             Application.Exit();
         }
     }
 }

Web服务器具体开发流程

forAddServer添加网站

 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Data;
 using System.Drawing;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows.Forms;

 namespace MyServer
 {
     public partial class forAddServer : Form
     {
         public forAddServer()
         {
             InitializeComponent();
         }
         public delegate void SiteDelegate(Site s);
         public event SiteDelegate SiteEvent;
         private void btnBrowse_Click(object sender, EventArgs e)
         {
             FolderBrowserDialog open = new FolderBrowserDialog();
             DialogResult result = open.ShowDialog();
             if(result == DialogResult.OK)//获得站点路径
             {
                 txtDirectory.Text = open.SelectedPath;
             }
         }

         private bool Valid(out string info) //判断格式
         {
             //此处没有做特殊处理,所以我在次提醒读者们
             bool flag = true;
             if (txtName.Text == "" || txtIP.Text == "" || txtPort.Text == "")
             {
                 flag = false;
                 info = "不能为空";
             }
             else
                 info = "添加成功!";
             return flag;
         }

         private void btnOK_Click(object sender, EventArgs e)
         {
             string info;
             if (Valid(out info))
                 MessageBox.Show(info);
             else
             {
                 MessageBox.Show(info);
                 return;
             }
             Site s = new Site() {
                     SiteName=txtName.Text,
                     IpAddress=txtIP.Text,
                     Path=txtDirectory.Text,
                     Port=txtPort.Text,
                     IsStart=false
             };
             SiteEvent(s);
         }

         private void btnCancel_Click(object sender, EventArgs e)
         {
             this.Close();
         }
     }
 }

Site站点类

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;

 namespace MyServer
 {
     [Serializable]
     public class Site//站点
     {
         public string SiteName { get;set; }
         public string IpAddress { get; set; }
         public string Port { get; set; }
         public string Path { get; set; }
         [NonSerialized]
         public bool IsStart;
     }
 }

Sites站点集合

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;

 namespace MyServer
 {
     [Serializable]
     public class Sites : List<Site>
     {
         //public List<Site> sites = new List<Site>();
         //public Sites(Site s)
         //{
         //    sites.Add(s);
         //}
     }
 }

HttpInfo拆分报文

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;

 namespace MyServer
 {
     public class HttpInfo
     {
         public string Method { get; set; }//GET POST
         public string Url { get; set; } //请求地址URL
         public string Protocol { get; set; }//使用的协议
         public string Other { get; set; }//其它

         public HttpInfo(string str)
         {
             string[] keys = str.Split(new string[] { "\r\n" }, StringSplitOptions.None);
             ].Split(' ');//GET /1.html HTTP/1.1

             ];//获取Get/Post方法
             ].Substring();
             ];

             this.Other = str;
         }
     }
 }

Response反应的内容

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;

 namespace MyServer
 {
     public class HttpResponse
     {
         public byte[] b = null;
         public string CreateOutHtml(string html)
         {
             StringBuilder sb = new StringBuilder();
             sb.Append("HTTP/1.1 200 OK\r\n");
             sb.Append("Content-Type: text/html\r\n");
             sb.Append("Last-Modified: Mon, 02 Dec 2013 12:21:06 GMT\r\n");
             sb.Append("Accept-Ranges: bytes\r\n");
             sb.Append("Server: Microsoft-IIS/7.5\r\n");
             sb.Append("Content-Length: 426\r\n\r\n");

             sb.Append(html);//连接上报文头部

             return html;
         }
     }
 }

HttpContext内容实体

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Net.Sockets;
 using System.Text;
 using System.Threading.Tasks;

 namespace MyServer
 {
     public class HttpContext
     {
         public string SitePath { get; set; }//路径地址
         public Socket TxSocket { get; set; }
         public HttpResponse Response { get; set; }//全部报文
         public HttpInfo Info { get; set; }//拆分报文获得想要的信息
         public HttpAllContext Context { get; set; }
     }
 }

HttpAllContext请求事件处理

 using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows.Forms;

 namespace MyServer
 {
     public class HttpAllContext
     {
         public delegate void ValidUserDelegate(HttpContext context);
         public delegate void LoadCache(HttpContext context);
         public delegate void LoadStatus(HttpContext context);
         public delegate void GeneratePage(HttpContext context);
         public delegate void WriteStatus(HttpContext context);

         //生成页面
         public event ValidUserDelegate ValidUserHandler;//报文头
         public event LoadCache LoadCacheHandler;
            public event LoadStatus LoadStatusHandler;
            public event GeneratePage GeneratePageHandler; //生成页面
         public event WriteStatus WriteStatusHandler;//状态

         //获取请求的参数:从context.Request
         //生成的页面:context.Response
         //支持客户自定义处理方式,扩展性-----事件    “管道技术”
         public void ProcessPage(HttpContext context)
         {
             if (ValidUserHandler != null) ValidUserHandler(context);
             if (LoadCacheHandler != null) LoadCacheHandler(context);
             if (LoadStatusHandler != null) LoadStatusHandler(context);
             if (GeneratePageHandler != null) GeneratePageHandler(context);
             if (WriteStatusHandler != null) WriteStatusHandler(context);
         }

      }
 }

Web服务器具体开发流程

HttpFactory工厂类

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;

 namespace MyServer
 {
     public abstract class HttpFactory
     {
         public static void CreateHandler(HttpContext con)
         {
             IHttpHead head = null;
             //获取该文件的后缀类型 xxx.html
             string extName = con.Info.Url.Substring(con.Info.Url.LastIndexOf('.'));
             switch (extName)
             {
                 case ".html": head = new HtmlHead(); break;
                 //case ".js": head = new JsHead(); break;
             }
             //添加事件
             con.Context.GeneratePageHandler += head.Process;
         }
     }
 }

IHttpHead//定义一个借口

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;

 namespace MyServer
 {
     public interface IHttpHead
     {
         void Process(HttpContext con);
     }
 }

HtmlHead子类

 using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows.Forms;

 namespace MyServer
 {
     public class HtmlHead : IHttpHead
     {

         public void Process(HttpContext context)
         {
             HttpInfo httpInfo = context.Info;//拆分报文类获得地址等
             //从报文中拆出请求的带路径html文件名
             string htmlFileName = context.SitePath + "\\" + httpInfo.Url;
             //如果有这个请求的文件就往下执行
             if (File.Exists(htmlFileName))
             {
                 //读取文件中的所有内容
                 string html = File.ReadAllText(htmlFileName);
                 //重新组装报文
                 html = context.Response.CreateOutHtml(html);
                 byte[] bb = Encoding.UTF8.GetBytes(html);
                 context.Response.b = bb;
                 MessageBox.Show("请求成功!");
             }
             else
             {
             }
         }
     }
 }
上一篇:GoldenGate配置(二)之双向复制配置


下一篇:ASP.NET jQuery 随笔 使用allValidator插件简单实现客户端验证功能