模拟服务器

一、使用窗体程序写一个简单的UI

 

 

 后台代码

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Net;
 8 using System.Net.Sockets;
 9 using System.Text;
10 using System.Threading;
11 using System.Threading.Tasks;
12 using System.Windows.Forms;
13 
14 namespace MyWebService
15 {
16     public partial class Form1 : Form
17     {
18         public Form1()
19         {
20             InitializeComponent();
21         }
22         Socket listenSocket = null;
23         /// <summary>
24         /// 启动服务
25         /// </summary>
26         /// <param name="sender"></param>
27         /// <param name="e"></param>
28         private void BtnStar_Click(object sender, EventArgs e)
29         {
30             listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建监控Socket
31             IPAddress iPAddress = IPAddress.Parse(txtIP.Text);//创建IP地址
32             IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, Convert.ToInt32(txtPort.Text));//创建网络节点
33             listenSocket.Bind(iPEndPoint);//绑定网络节点
34             listenSocket.Listen(10);//监听队列10
35             //只有监听到一个连接,代码才会继续往下走,会影响UI线程,所以开启一个线程专门监听
36             Thread myThread = new Thread(BeginAccept);
37             myThread.IsBackground = true;
38             myThread.Start();
39         }
40         /// <summary>
41         /// 监听浏览器发送的请求,当有浏览器发送请求时,创建一个新的Socket处理客户请求,使用死循环继续监听下一个用户的请求
42         /// </summary>
43         private void BeginAccept()
44         {
45             while (true)//监听Socket继续监听
46             {
47                 Socket socket = listenSocket.Accept();//将连接交给一个新创建的Socket
48                 //对请求进行处理
49                 HttpApplication httpApplication = new HttpApplication(socket, ShowMsg);
50             }
51         }
52         /// <summary>
53         /// 对跨线程访问进行处理
54         /// </summary>
55         /// <param name="msg"></param>
56         private void ShowMsg(string msg)
57         {
58             if (txtMsg.InvokeRequired)
59             {
60                 txtMsg.Invoke(new Action<string>((mgs) =>
61                 {
62                     this.txtMsg.Text = msg+"\r\n";
63                 }), msg);
64             }
65         }
66     }
67 }

使用HttpApplication类对发送来的请求做处理

 1 using System;
 2 using System.Collections.Generic;
 3 using System.IO;
 4 using System.Linq;
 5 using System.Net.Sockets;
 6 using System.Text;
 7 using System.Threading.Tasks;
 8 
 9 namespace MyWebServer
10 {
11     /// <summary>
12     /// 完成客户端发送过来的数据的处理。
13     /// </summary>
14     public class HttpApplication
15     {
16         Socket newSocket = null;
17         DGShowMsg dgShowMsg = null;
18         /// <summary>
19         /// HttpApplication构造函数
20         /// </summary>
21         /// <param name="newSocket">需要处理的Socket对象</param>
22         /// <param name="dgShowMsg">窗体程序的文本框</param>
23         public HttpApplication(Socket newSocket, DGShowMsg dgShowMsg)
24         {
25             this.newSocket = newSocket;
26             this.dgShowMsg = dgShowMsg;
27             //接收客户端发送过来的数据.
28             byte[] buffer = new byte[1024 * 1024 * 2];
29             int receiveLength = newSocket.Receive(buffer);//接收客户端发送过来的数据,返回的是实际接收的数据的长度。
30             //如果发过来的请求有数据,才进行处理
31             if (receiveLength > 0)
32             {
33                 string msg = System.Text.Encoding.UTF8.GetString(buffer, 0, receiveLength);
34                 HttpRequst request = new HttpRequst(msg);
35                 ProcessReuest(request);
36                 dgShowMsg(msg);
37             }
38         }
39         /// <summary>
40         /// 对请求做处理,并响应
41         /// </summary>
42         /// <param name="request"></param>
43         public void ProcessReuest(HttpRequst request)
44         {
45             string filePath = request.FilePath;
46             string dataDir = AppDomain.CurrentDomain.BaseDirectory;//获得当前服务器程序的运行目录
47             if (dataDir.EndsWith(@"\bin\Debug\") || dataDir.EndsWith(@"\bin\Release\"))
48             {
49                 dataDir = System.IO.Directory.GetParent(dataDir).Parent.Parent.FullName;
50             }
51             string fullDir = dataDir + filePath;//获取文件完整路径。
52             using (FileStream fileStream = new FileStream(fullDir, FileMode.Open, FileAccess.Read))
53             {
54                 byte[] buffer = new byte[fileStream.Length];
55                 fileStream.Read(buffer, 0, buffer.Length);
56                 //构建响应报文。
57                 HttpResponse response = new HttpResponse(buffer, filePath);
58                 newSocket.Send(response.GetHeaderResponse());//返回响应头.
59                 newSocket.Send(buffer);
60             }
61         }
62     }
63 }

这是请求报文

GET /Show.html HTTP/1.1

Host: 127.0.0.1:9876

Connection: keep-alive

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3554.0 Safari/537.36

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

Accept-Encoding: gzip, deflate, br

Accept-Language: zh-CN,zh;q=0.9

 

HttpRequest类:对请求报文头进行处理

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace MyWebService
 8 {
 9     public class HttpRequest
10     {
11         /// <summary>
12         /// 请求文件相对路径
13         /// </summary>
14         public string filePath { get; set; }
15         public HttpRequest(string msg)
16         {
17             filePath = msg.Split(' ')[1];
18         }
19     }
20 }

HttpResponse类

 1 using System;
 2 using System.Collections.Generic;
 3 using System.IO;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace MyWebService
 9 {
10     public class HttpResponse
11     {
12         byte[] buffer;
13         /// <summary>
14         /// 报文体返回类型
15         /// </summary>
16         public string Content_Type { get; set; }
17         /// <summary>
18         /// HttpResponse构造函数
19         /// </summary>
20         /// <param name="buffer">报文体字节数组</param>
21         /// <param name="fliePath">文件绝对路径</param>
22         public HttpResponse(byte[] buffer, string fliePath)
23         {
24             this.buffer = buffer;
25             string fileExt = Path.GetExtension(fliePath);//获取响应文件扩展名,返回相应的报文体返回类型
26             switch (fileExt)
27             {
28                 case ".html":
29                     Content_Type = "text/html";
30                     break;
31             }
32         }
33         /// <summary>
34         /// 获取返回报文头
35         /// </summary>
36         /// <returns></returns>
37         public byte[] GetResonseHead()
38         {
39             StringBuilder builder = new StringBuilder();
40             builder.Append("HTTP/1.1 200 ok\r\n");
41             builder.Append("Content-Type:" + Content_Type + ";charset=utf-8\r\n");
42             builder.Append("Content-Length:" + buffer.Length + "\r\n\r\n");//在相应报文头的最后一行下面有一个空行,所以在这里加两组"\r\n"
43             return System.Text.Encoding.UTF8.GetBytes(builder.ToString());
44         }
45     }
46 }

Show.html

<!DOCTYPE html>

 

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>

    <meta charset="utf-8" />

    <title></title>

</head>

<body>

    我的博客.

</body>

</html>

最后我们来用一下

点击启动调试,然后启动服务

 

 

 

 

 

 然后再浏览器输入,请求地址

 

 

 最后的结果就是

 

 

 

 

 

 

posted on 2019-11-18 20:56  爱写代码的鸟  阅读(719)  评论(0编辑  收藏  举报