用C#实现Web代理服务器

代理服务程序是一种广泛使用的网络应用程序。代理程序的种类非常多,根据协议不同可以分成HTTP代理服务程序、FTP代理服务程序等,而运行代理服务程序的服务器也就相应称为HTTP代理服务器和FTP代理服务器。本文将介绍的Web代理服务程序代理的是HTTP协议。

  一、网络代理程序的优点

  代理服务所起的是一个桥的作用,它是网络信息的中转站。在网络中应用代理服务一般是基于以下几个原因:

  (1)充分利用IP地址资源。在局域网中,一般对外的IP地址都是非常有限的,为了保证局域网内部的主机都能够访问互联网资源,通过网络代理就可以实现。
  (2)能够保证网络安全。网络代理可以充当内部网和互联网之间的防火墙,通过过滤IP地址,限定某些IP地址对外部资源的访问。
  (3)能够有效地隐藏自己的IP地址和主机名。由于所有对外网的请求都是通过代理服务器实现的,所以目的主机只能知道代理服务器的IP地址。
  (4)提高网络速度。通常代理服务器都设有一个较大的硬盘缓冲区,它存储界数据,当你再访问相同的数据时,则可以直接从缓冲区中取出信息,从而提高访问速度。

  二、网络代理的类型及实现原理

  网络代理服务根据工作层次,一般可分为应用层代理、传输层代理和SOCKS代理。应用层代理是工作在TCP/IP参考模型的应用层之上,它支持对应用层协议(如HTTP、FTP)的代理。它提供的控制最多,但是不灵活,必须要有相应的协议支持。如果协议不支持代理(如SMTP和POP),那就只能在应用层以下代理,也即传输层代理。传输层代理直接与TCP层交互,更加灵活。要求代理服务器具有部分真正服务器的功能:监听特定TCP或UDP端口,接收客户端的请求同时向客户端发出相应的响应。另一种代理需要改变客户端的IP栈,即SOCKS代理。它是可用的最强大、最灵活的代理标准协议。SOCK V4允许代理服务器内部的客户端完全地连接到外部的服务器,SOCK V5增加了对客户端的授权和认证,因此它是一种安全性较高的代理。本节后面介绍的代理是一种应用层上面的代理,所代理的协议是HTTP,也就是经常见到的Web代理。

  正如上面所说,网络代理就是一个连接客户端(需要代理的计算机)和服务器端(提供访问资源的服务器)的桥。要实现这种桥的功能,网络代理就必须满足下列条件,其实也是代理服务的运行的流程:

  (1)接收并解析客户端的请求。
  (2)创建到服务器的新连接,并转发客户端的请求信息。
  (3)接收服务器反馈的信息。
  (4)解释服务器的响应并将该响应传回给客户端。

  图1是网络代理服务的一个典型模型图:

  
  网络代理虽然有很多优点,但由于使用代理后,自己对网络的所有请求都是通过代理服务器这个中间人来实现的,所以有可能碰上存有恶意的人监听你的输入的内容。同样,如果选择的代理服务器的带宽比较小,使用代理还会降低网速。

  总而言之,使用代理有利有弊,使用者要根据自身的情况来决定。但无论如何,选择一个好的代理服务器是非常重要的。

三、C#实现Web代理服务程序

  经过了上面的介绍,我想大家对代理服务应该有了一个基本的认识,下面就让我们通过一个实例来深入体会一下如何用C#实现Web代理服务。Web代理服务的功能顺序是这样的:

  (1)侦听端口,等待客户端浏览器发送来的Web请求信息。
  (2)接收到客户端Web请求信息后,解析出目标Web服务器的地址,并创建一个Socket实例,并以此实例连接Web服务器上。
  (3)通过创建的Socket传送客户端的Web请求数据包到Web服务器的80端口。
  (4)接收Web服务器返回的页面数据。
  (5)把接收来的数据传送到客户端,从而实现Web代理。

  客户端对某个Web地址的浏览,可能要传送很多的Web请求信息(比如网页中的图像、Flash等),为了更快更准确地处理这些信息,Web代理服务程序通常采用多线程来处理每一个Web请求。细心的读者可能会发现,处理每一个客户端的Web请求信息,代理服务器软件都要使用二个Socket,一个是用来接收/传送客户机的信息,一个是和Web服务器进行交流。为了区分这二个Socket,我们把和服务器对话的称为“服务Socket”,和客户端机器对话的称为“客户Socket”。

  下面就开始Web代理服务程序的编写工作。这个实例包含三个部分内容:

  1.创建一个Web代理类。
  2.Web代理服务的类的实例化。
  3.如何通过这个Web代理类的实例实现Web代理服务。

  (一)创建一个Web代理类

  具体操作步骤如下:

  1.启动Visual Studio.Net,依次选择“文件”、“新建”、“项目”菜单后,在弹出“新建项目”对话框中将“项目类型”设置为“Visual C#项目”,将“模板”设置为“Windows应用程序”,在“名称”文本框中输入“WebProxy”,在“位置”文本框中输入“E:VS.NET项目”,然后单击“确定”按钮,这样项目便建立好了。
  2.依次选择菜单“项目”、“添加类”,将弹出“添加新项”对话框。
  3.将“模板”设置为“类”。
  4.在“名称”文本框中输入“Proxy”,单击“打开”按钮,具体如图2所示:
  5.在“解决方案资源管理器”窗口中,双击Proxy.cs文件,进入Proxy.cs文件的编辑界
  6.在Proxy.cs源文件的开头,添加下列代码,下列代码是导入Proxy.cs中要使用到的命名空间:

  using System;
  using System.Net;
  using System.Net.Sockets;
  using System.Text;
  using System.IO;

  7.用下列构造函数替代默认的构造函数。下面的代码是在Proxy类中创建一个构造函数。Proxy类只有一个构造函数,并且这个构造函数只有一个参数,这个参数是Socket对象,它主要用来和客户端进行数据交换,是一个“客户Socket”:

  public Proxy(Socket socket)
  {
  //
  // TODO: 在此处添加构造函数逻辑
  //
  this.clientSocket = socket ;
  }

  8.在定义Proxy类代码区中加入下列代码,下列代码是定义Proxy类中的使用的一些变量,这些变量主要是在后面的定义Run方法中使用。

  Socket clientSocket;
  Byte[] read = new byte[1024];
  //定义一个空间,存储来自客户端请求数据包
  Byte [] Buffer = null;
  Encoding ASCII = Encoding.ASCII;
  //设定编码
  Byte[] RecvBytes = new Byte[4096];
  //定义一个空间,存储Web服务器返回的数据

9.创建Proxy类中的Run方法。Run方法是Proxy类中唯一的方法。其功能是从客户端接收HTTP请求,并传送到Web服务器,然后从Web服务器接收反馈来的数据,并传送到客户端。为了实现这二个不同方面的数据传送,Run方法中是通过两个Socket实例来实现的。在编写Run方法的时候,要注意下面两点:

  (1)由于HTTP建立于TCP协议之上,所以创建的Socket实例应该使用TCP协议。下面代码是创建可以传送HTTP请求命令到Web服务器和接收来自Web服务器反馈来信息的Socket实例:

  Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

  (2)另外一个Socket是在代理服务程序侦听端口号,接收连接请求时候得到的,所以应该以此Socket为参数,利用Proxy类中的构造函数来创建一个Proxy实例。此Socket实现从客户端接收HTTP请求信息,并传送数据到客户端。

  Socket创建和使用是实现Web代理软件的关键。在构造函数代码后面,输入下列代码:
  public void Run()
  {
  string clientmessage = " " ;
  //存放来自客户端的HTTP请求字符串
  string URL = " " ;
  //存放解析出地址请求信息
  int bytes = ReadMessage(read, ref clientSocket, ref clientmessage);
  if (bytes == 0)
  {
  return ;
  }
  int index1 = clientmessage.IndexOf(' ');
  int index2 = clientmessage.IndexOf(' ', index1 + 1);
  if ((index1 == -1) || (index2 == -1))
  {
  throw new IOException();
  }
  string part1 = clientmessage.Substring(index1 + 1, index2 - index1);
  int index3 = part1.IndexOf('/', index1 + 8);
  int index4 = part1.IndexOf(' ', index1 + 8);
  int index5 = index4 - index3;
  URL = part1.Substring(index1 + 4, (part1.Length - index5) - 8); 
  try
  {
  IPHostEntry IPHost = Dns.Resolve(URL);
  Console.WriteLine("远程主机名: " + IPHost.HostName);
  string [] aliases = IPHost.Aliases;
  IPAddress[] address = IPHost.AddressList;
  Console.WriteLine("Web服务器IP地址:" + address[0]);
  //解析出要访问的服务器地址
  IPEndPoint ipEndpoint = new IPEndPoint(address[0], 80);
  Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  //创建连接Web服务器端的Socket对象
  IPsocket.Connect(ipEndpoint);
  //Socket连Web接服务器
  if (IPsocket.Connected)
  Console.WriteLine("Socket 正确连接!");
  string GET = clientmessage;
  Byte[] ByteGet = ASCII.GetBytes(GET);
  IPsocket.Send(ByteGet, ByteGet.Length, 0);
  //代理访问软件对服务器端传送HTTP请求命令
  Int32 rBytes = IPsocket.Receive(RecvBytes, RecvBytes.Length, 0);
  //代理访问软件接收来自Web服务器端的反馈信息
  Console.WriteLine("接收字节数:" + rBytes.ToString());
  String strRetPage = null;
  strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, rBytes);
  while (rBytes > 0)
  {
  rBytes = IPsocket.Receive(RecvBytes, RecvBytes.Length, 0);
  strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, rBytes);
  }
  IPsocket.Shutdown(SocketShutdown.Both);
  IPsocket.Close();
  SendMessage(clientSocket, strRetPage);
  //代理服务软件往客户端传送接收到的信息
  }
  catch (Exception exc2)
  
  }
  
  //接收客户端的HTTP请求数据
  private int ReadMessage(byte [] ByteArray, ref Socket s, ref String clientmessage)
  {
  int bytes = s.Receive(ByteArray, 1024, 0);
  string messagefromclient = Encoding.ASCII.GetString(ByteArray);
  clientmessage = (String)messagefromclient;
  return bytes;
  }
  
  //传送从Web服务器反馈的数据到客户端
  private void SendMessage(Socket s, string message)
  {
  Buffer = new Byte[message.Length + 1];
  int length = ASCII.GetBytes(message, 0, message.Length, Buffer, 0);
  Console.WriteLine("传送字节数:" + length.ToString());
  s.Send(Buffer, length, 0);
  }

  至此,Proxy类的定义过程就完成了。

  (二)利用Proxy类,实现Web代理

  下面是利用Proxy类实现Web代理程序的具体实现步骤,Proxy类被定义在命名空间  WebProxy中:

  1.在Visual Studio .Net的代码编辑器中打开Class1.cs文件,进入Class1.cs的代码编辑界面。

  2.在Class1.cs源文件的开头导入下列命名空间:

  using System;
  using System.Net;
  using System.Net.Sockets;
  using System.Text;
  using System.IO;
  using System.Threading;
  using WebProxy;

  3.在Main函数中添加下列代码,下列代码是利用Proxy类,来实现Web代理程序:

  const int port = 8000 ;
  //定义端口号
  TcpListener tcplistener = new TcpListener(port);
  Console.WriteLine("侦听端口号: " + port.ToString());
  tcplistener.Start();
  //侦听端口号
  while (true)
  {
  Socket socket = tcplistener.AcceptSocket();
  //并获取传送和接收数据的Scoket实例
  Proxy proxy = new Proxy(socket);
  //Proxy类实例化
  Thread thread = new Thread(new ThreadStart(proxy.Run));
  //创建线程
  thread.Start();
  //启动线程
  }

  保存上面的所有步骤,这样一个简单Web代理程序就算是完成了。此Web代理程序侦听的是8000端口号。

  (三)测试Web代码程序

  Web代理程序要通过二台计算机才能够实现,其中的一台计算机运行Web代理程序充当Web代理服务器,另外一台计算机充当客户机,通过Web代理服务器来浏览网页。在确定Web代理软件运行后,需要对客户机进行进行必要的设置:

  1.打开IE浏览器。

  2.依次选择“工具”、“Internet选项”,在弹出的“Internet选项”对话框中选择“连接”页面,单击其中的“局域网设置”按钮,在弹出的“局域网(LAN)设置”对话框,选择“为LAN使用代理服务器(X),(这些设置不会应用于拨号和VPN连接)”多选框,并在其中的“地址”文本框中输入代理服务器的IP地址,比如“10.138.198.213”,在“端口”文本框中输入“8000”。 此时客户端的设置就完成了。在确定IP地址为“10.138.198.213”的这台计算机已经运行上面介绍的Web代理程序后,打开客户端的IE浏览器,并输入要浏览的网址,就可以通过Web代理服务器来浏览网页了。

  四、总结

  至此一个简单的Web代理服务软件就算基本完成了。虽然代理服务的实现原理相对简单,但具体实现还是很繁琐的。网络代理是一个内容丰富,实现复杂的论题,本节介绍的代理服务软件,无论在实现的协议种类,还是实现的功能,都只能算很小的一部分。希望各位能够通过本文的介绍,结合其他相关的知识,创造出功能更强大、安全性更高,使用更稳定的网络代理服务程序来。

用C#实现WEB代理服务器的更多相关文章

  1. ASP.NET Core 实现带认证功能的Web代理服务器

    引言 最近在公司开发了一个项目,项目部署架构图如下: 思路 如图中文本所述,公司大数据集群不允许直接访问外网,需要一个网关服务器代理请求,本处服务器A就是边缘代理服务器的作用. 通常技术人员最快捷的思 ...

  2. 浅谈C#实现Web代理服务器的几大步骤

    代理服务程序是一种广泛使用的网络应用程序.代理程序的种类非常多,根据协议不同可以分成HTTP代理服务程序.FTP代理服务程序等,而运行代理服务程序的服务器也就相应称为HTTP代理服务器和FTP代理服务 ...

  3. 五大开源 Web 代理服务器横评:Squid、Privoxy、Varnish、Polipo、Tinyproxy

    https://linux.cn/article-7119-1.html Web 代理软件转发 HTTP 请求时并不会改变数据流量.它们可以配置成透明代理,而无需客户端配置.它们还可以作为反向代理放在 ...

  4. Web服务及http协议

    HTTP:HyperText Transfer Protocol--超文本传输协议 超链接:能够在文档之间跳转的文本 早起的Web:仅仅是能够实现在文档之间跳转的一种协议 http/0.9:仅支持纯文 ...

  5. Web 技术人员需知的 Web 缓存知识(转)

    最近的译文距今已有4年之久,原文有一定的更新.今天踩着前辈们的肩膀,再次把这篇文章翻译整理下.一来让自己对web缓存的理解更深刻些,二来让大家注意力稍稍转移下,不要整天HTML5, 面试题啊叨啊叨的~ ...

  6. Web 技术人员需知的Web 缓存知识

    最近的译文距今已有4年之久,原文有一定的更新.今天踩着前辈们的肩膀,再次把这篇文章翻译整理下.一来让自己对web缓存的理解更深刻些,二来让大家注意力稍稍转移下,不要整天HTML5, 面试题啊叨啊叨的~ ...

  7. Web开发人员需知的Web缓存知识

    最近的译文距今已有4年之久,原文有一定的更新.今天踩着前辈们的肩膀,再次把这篇文章翻译整理下.一来让自己对web缓存的理解更深刻些,二来让大家注意力稍稍转移下,不要整天HTML5, 面试题啊叨啊叨的~ ...

  8. 浅谈web缓存(转)

    这是一篇知识性的文档,主要目的是为了让Web缓存相关概念更容易被开发者理解并应用于实际的应用环境中.为了简要起见,某些实现方面的细节被简化或省略了.如果你更关心细节实现则完全不必耐心看完本文,后面参考 ...

  9. 什么是Web缓存控制(基于HTTP头域)

    这是一篇转载的知识性的文档,主要目的是为了让Web缓存相关概念更容易被开发者理解并应用于实际的应用环境中.为了简要起见,某些实现方面的细节被简化或省略了.如果你更关心细节实现则完全不必耐心看完本文,后 ...

随机推荐

  1. 菜鸟学习Spring——SpringMVC注解版在服务器端获取Json字符串并解析

    一.概述. SpringMVC在服务端把客户端传过来的JSON字符串,并把JSON字符串转成 JSON对象并取得其中的属性值,这个在项目中经常用到. 二.代码演示. 需要添加的jar包. 2.1 we ...

  2. Learn by pictures on Auto Control Fields

  3. 《ArcGIS Runtime SDK for Android开发笔记》——(11)、ArcGIS Runtime SDK常见空间数据加载

    ArcGIS Runtime SDK for Android 支持多种类型空间数据源.每一种都提供了相应的图层来直接加载,图层Layer是空间数据的载体,其主要继承关系及类型说明如下图所示: 转载请注 ...

  4. 使用canvas来绘制折线图

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. python编写的简单的mysql巡检脚本

    准备工作:1    安装python 3.5,本次使用源码安装.2    安装psutil模块,使用python3.5自带的easy_install包直接运行cd /opt/python3/bin./ ...

  6. 限定filesize的数据泵导入导出操作案例

    使用如下方法导入导出expdp sh/sh dumpfile=ycr_%U.dump directory=exp filesize=2mimpdp sh/sh dumpfile=ycr_%U.dump ...

  7. expdp/impdp使用sysdba权限迁移数据

    expdp 'userid="/ as sysdba"' directory=DATA_PUMP_DIR full=y logfile=fullexp.log estimate_o ...

  8. css渲染(三)颜色与背景

    颜色的应用主要分为前景色.背景色和透明三个部分. 一.前景色 color color前景色 值: <color> | inherit 初始值: 用户代理特定的值 应用于: 所有元素 继承性 ...

  9. scrum3

    首先我一直做的是框架的设计,但不同的是这次我们整合完善了这个软件目前的所有需求也定义好了它的大题框架,总的来说设计部分已经结束,现在也就是本次冲刺,我们将重点进行整个软件的数据库编程环节,也就是用SQ ...

  10. Locust性能测试1 脚本编写与运行

    按照官网的quickstart编写脚本并运行 1  编写脚本 2  locust -f  filepath 启动locust 3 浏览器打开localhost:8089,设置并发用户数和每秒启动用户数 ...