欢迎光临
我们一直在努力

C#中使用Socket实现简单Web服务器

上一篇博客中介绍了怎样使用socket访问web服务器。关键有两个:

  • 熟悉Socket编程;
  • 熟悉HTTP协议。

上一篇主要是通过socket来模拟浏览器向(任何)Web服务器发送(HTTP)请求,重点在浏览器端。本篇博客则反过来讲一下怎样使用socket来实现Web服务器,怎样去接收、分析、处理最后回复来自浏览器的HTTP请求。

HTTP协议是浏览器和Web服务器都需要遵守的一种通信规范,如果我们编写一个程序,正确遵守了HTTP协议,那么理论上讲,这个程序可以具备浏览器、甚至Web服务器的功能。

C#中使用Socket实现简单Web服务器

图1

如上图1所示,Web服务器和浏览器之间无论是发送数据还是接收(解析)数据均遵守了HTTP协议。可以很确定地讲,只要我们充分熟悉HTTP协议结构,那么无论浏览器的实现还是Web服务器的实现,均只是“简单的”Socket程序的开发过程,除此之外,无其它神秘高深的东西。而Socket程序开发,稍微知道一点socket的有关知识,均能写得出一个大概demo。

从系统架构来讲,Web架构形式的系统均符合“生产者-消费者”模式(实质上,现实生活中大部分系统均属于该模式)。浏览器端不断产生数据(请求),而Web服务器端不断处理请求,长时间持续如此。

C#中使用Socket实现简单Web服务器

图2

如上图2所示,图中左边部分为Web服务器中的“泵”结构,所谓泵,就是指它能够持续长时间循环运作。图中右边显示“来自浏览器请求”部分即为“生产者”,生产者不断发出请求,由左边(Web服务器)不断进行处理,最后回复给浏览器。注意图2中显示,Web服务器中处理数据在循环体内部,换句话说,前一次HTTP请求处理结束之前,后一次HTTP请求不能开始,也就是每次请求处理均会阻塞循环的执行。这种串行处理数据的方式明显效率不高,为了解决该问题,我们可以在接收到浏览器端的HTTP请求后,并不马上在当前线程中进行处理,而是开辟独立线程来处理请求(在.NET中可以使用异步编程实现)。这样一来,请求处理并不会阻塞当前循环过程,见下图3

C#中使用Socket实现简单Web服务器

图3

如上图3所示,接收到请求后,开辟其它线程来处理,这种并行处理数据的方式不会影响后续请求处理。

如果对Socket编程比较熟悉,以上所说的完全可以轻松实现(完全按照Socket编程去做)。现在难点是,Web服务器端怎样解析来自浏览器的请求数据(一串字符串文本),以及应该以怎样的格式去回复浏览器?答案就是必须充分了解HTTP协议格式。上一篇博客中已经提到过,有关HTTP协议格式请参见http://www.cnblogs.com/riky/archive/2007/04/09/705848.html。我们必须读懂浏览器发送的请求数据,并按照正确格式发送回复。下图4显示浏览器请求数据格式:

C#中使用Socket实现简单Web服务器

图4

图中红色部分即为数据传输方式(post或get)、请求路径(url中不含主机地址部分)以及HTTP协议版本号。下面以“键:值”格式的文本均为浏览器发送给服务器的一系列数据信息(注意这些项可选),如果浏览器以post方式提交数据,那么数据会紧跟在下面(图中没显示)。Web服务器读懂浏览器发送的请求数据,并处理完毕后,必须按照图5的格式将结果回复给浏览器:

C#中使用Socket实现简单Web服务器

图5

如上图5所示,最上面的以“键:值”的格式文本是Web服务器发送给浏览器的一些数据信息(这些项部分可选),紧接着,下面便是需要发送给浏览器的HTML文档(如果返回的是页面)。浏览器必须读懂Web服务器发送的回复数据,然后进行渲染(显示)。

C#中使用Socket实现简单Web服务器

图6

图6显示了浏览器发起的一次HTTP请求,显示展示了Web服务器端处理该请求的过程。我们可以看到,Web服务器在一次Socket连接过程中只处理一个HTTP请求。多次HTTP请求会伴随着Socket不断的连接与断开。

文章最后上传一个使用Socket编写的简单Web服务器,能够实现以下功能:

  • 运行Web服务器后,可以绑定端口,接收来自任何浏览器的HTTP请求;
  • 能够显示一个默认首页,如index.html;
  • 首页提供“登录”功能,按照Post方式传递数据到处理页面“login.zsp”(后缀名可自定义);
  • Web服务器端接收接收浏览器发送的数据,能够解析(解析方式很随意)出post传递的参数,并模拟访问数据库检查登录情况、模拟耗时等待等;
  • Web服务器生成登录成功后的静态页,回复给浏览器。页面显示登录名和当前时间。

整个demo完全就是一个Socket程序,只是增加了“HTTP协议”的环节,服务器端无论是接收(解析)数据还是发送数据,均需要遵守HTTP协议。Web服务器中最终的请求处理泵代码如下:

C#中使用Socket实现简单Web服务器C#中使用Socket实现简单Web服务器

 1 static Socket _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //侦听socket  2 static void Main(string[] args)  3  {  4 _socket.Bind(new IPEndPoint(IPAddress.Any, 8081));  5 _socket.Listen(100);  6 _socket.BeginAccept(new AsyncCallback(OnAccept), _socket); //开始接收来自浏览器的http请求(其实是socket连接请求)  7  Console.Read();  8  }  9 static void OnAccept(IAsyncResult ar) 10  { 11 try 12  { 13 Socket socket = ar.AsyncState as Socket; 14 Socket new_client = socket.EndAccept(ar); //接收到来自浏览器的代理socket 15 //NO.1 并行处理http请求 16 socket.BeginAccept(new AsyncCallback(OnAccept), socket); //开始下一次http请求接收 (此行代码放在NO.2处时,就是串行处理http请求,前一次处理过程会阻塞下一次请求处理) 17 18 byte[] recv_buffer = new byte[1024 * 640]; 19 int real_recv = new_client.Receive(recv_buffer); //接收浏览器的请求数据 20 string recv_request = Encoding.UTF8.GetString(recv_buffer, 0, real_recv); 21 Console.WriteLine(recv_request); //将请求显示到界面 22 23 Resolve(recv_request,new_client); //解析、路由、处理 24 25 //NO.2 串行处理http请求 26  } 27 catch 28  { 29 30  } 31 }

View Code

注意以上代码中的NO.1和NO.2处,socket.BeginAccept()方法放在NO.1处时,服务器端会并行处理请求,而放在NO.2处时,服务器会串行处理请求。读者可以每种方式都试一下,在串行处理请求时,请求处理过程会阻塞后续请求的处理(比如登录耗时10秒钟,其它人无法访问网站)。

以下是demo效果图:

图7:Web服务器运行后,浏览器访问首页:

C#中使用Socket实现简单Web服务器

图7

图8:浏览器中首页显示(包含登录框):

C#中使用Socket实现简单Web服务器

图8

图9:用户点击“登录”按钮,以Post方式提交数据,Web服务器解析、处理,返回新页面:

C#中使用Socket实现简单Web服务器

图9

文章有点长,部分截图还失真了(部分图以前整理的,没有找到大图,所以就凑合看:))

源码下载:https://files.cnblogs.com/xiaozhi_5638/socket_webServer.rar

  • 海报
海报图正在生成中...
赞(0) 打赏
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
文章名称:《C#中使用Socket实现简单Web服务器》
文章链接:https://www.456zj.com/3726.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址