| 网站首页 | 资讯 | Hack | 漏洞 | 网管 | 编程 | 培训 | 品黑页 | 软件 | 论坛 | 动画 | 视频 | 经典 | 教学站 | 黑客点睛 | 
服务导航 我要发布 主力频道 空间域名 精华收集 服务器出租 黑客培训 光盘刻录 特色服务 解决方案 我要投诉
您现在的位置: 华夏黑客同盟 >> 编程 >> C语言 >> 正文 用户登录 新用户注册
粗糙的C#版HTTP代理         ★★★ 【字体:
粗糙的C#版HTTP代理
作者:云舒 文章来源:华盟收集 点击数: 更新时间:2008-8-7

  前些时候一个无锡人在我博客留言,说我读再多的书,也改变不了我是个程序员的本质。或许它觉得它是在鄙视我,不过我到觉得它是在赞扬我——我真的算不上是个程序员,写代码的能力实在是太烂了——不过我会努力的。

  说说这段代码的问题吧。首先是字符串切割的问题,要将客户端提交过来的GET,POST等原始请求切割,分离出主机名,端口,URL等数据。这里用正则匹配是最好的,遗憾的是我不擅长此道,所以使用了手动切割的办法,很笨重繁琐,但是毕竟它工作得很好。第二个问题是Keep-Alive的问题,这里我没有处理好。最开始我在http proxy里面修改客户端请求,强行将keep-alive修改为close,但是发现在某些站点的时候会出错。于是使用了类似select的方法读取数据,直到超时关闭两端的连接。我猜测,这里如果解析content-length会更好,但是略微繁琐了点,还是等我仔细阅读下RFC再看怎么修改吧。第三个是CONNECT方法的问题,这个到很简单,转发数据就行了,因此是这个代码中写得最好的一部分,用来登陆QQ还是不错的。

  说实话,我不喜欢HTTP这种太宽松的协议,感觉灵活得让我难以把握。直接看代码吧,我加了很多debug信息,真的要用就去掉好了。调用这个类很简单,看main函数的实现就好了。为了方便贴代码,我写的时候就把三个类写到一个文件里面去了。顺便要说的是,虽然有类,但是没有任何面向对象的东西——这也再次证明,其实我算不上一个程序员,最多是个代码爱好者。

using System;
 
 using System.Net;
 
 using System.Net.Sockets;
 
 using System.Text;
 
 using System.IO;
 
 using System.Threading;
 
 using System.Collections;
 
 
 
 namespace HttpProxy
 
 {
 
 public class HttpProxy
 
 {
 
 int ProxyPort;
 
 
 
 /// <summary>
 
 /// 代理服务器入口类构造函数
 
 /// </summary>
 
 /// <param name="Port">Http Proxy监听的端口</param>
 
 public HttpProxy( int Port)
 
 {
 
 ProxyPort = Port;
 
 }
 
 
 
 /// <summary>
 
 /// 启动Http代理服务器
 
 /// </summary>
 
 public void Start( )
 
 {
 
 TcpListener tcplistener = null;
 
 try
 
 {
 
 // 开始监听端口
 
 tcplistener = new TcpListener(Dns.GetHostAddresses(Dns.GetHostName())[0], ProxyPort);
 
 tcplistener.Start();
 
 Console.WriteLine("侦听端口号: " + ProxyPort.ToString());
 
 }
 
 catch (Exception e)
 
 {
 
 Console.WriteLine("启动代理服务器失败: " + e.Message);
 
 }
 
 
 
 while (true)
 
 {
 
 try
 
 {
 
 // 接受客户端连接
 
 Socket socket = tcplistener.AcceptSocket();
 
 
 
 HttpSession Session = new HttpSession(socket);
 
 
 
 // 启动新线程,处理连接
 
 Thread thread = new Thread(new ThreadStart(Session.Start));
 
 thread.Start();
 
 }
 
 catch( Exception e )
 
 {
 
 Console.WriteLine("接受客户端连接异常: " + e.Message );
 
 }
 
 }
 
 
 
 }
 
 }
 
 
 
 public class HttpSession
 
 {
 
 // 客户端socket
 
 Socket ClientSocket;
 
 
 
 // 设定编码
 
 Encoding ASCII = Encoding.ASCII;
 
 
 
 /// <summary>
 
 /// 构造函数
 
 /// </summary>
 
 /// <param name="socket">客户端socket</param>
 
 public HttpSession(Socket socket)
 
 {
 
 this.ClientSocket = socket;
 
 }
 
 
 
 public void Start()
 
 {
 
 // 客户端缓冲区,读取客户端命令
 
 Byte[] ReadBuff = new byte[1024 * 10];
 
 
 
 try
 
 {
 
 int Length = ClientSocket.Receive(ReadBuff);
 
 
 
 // 没有读到数据
 
 if (0 == Length)
 
 {
 
 Console.WriteLine("从客户端读取命令错误");
 
 ClientSocket.Shutdown(SocketShutdown.Both);
 
 ClientSocket.Close();
 
 
 
 return;
 
 }
 
 }
 
 // 读取出现异常
 
 catch (Exception e)
 
 {
 
 Console.WriteLine("读取客户端异常: " + e.Message);
 
 }
 
 
 
 // 来自客户端的HTTP请求字符串
 
 string ClientMsg = ASCII.GetString(ReadBuff);
 
 
 
 // 根据rnrn截取请求行
 
 string Line = ClientMsg.Substring(0, ClientMsg.IndexOf("rn"));
 
 string[] CmdArray = Line.Split(' ');
 
 
 
 // GET http://www.test.com:80/index.php HTTP/1
 
 // CONNECT www.test.com:443 HTTP/1
 
 string Cmd = CmdArray[0];
 
 string RawUrl = CmdArray[1];
 
 
 
 Console.WriteLine("原始请求: ", Line);
 
 
 
 // CONNECT请求
 
 if (Cmd == "CONNECT")
 
 {
 
 DoConnect(RawUrl);
 
 }
 
 // GET,POST和其他
 
 else
 
 {
 
 DoOther(RawUrl, ClientMsg);
 
 }
 
 }
 
 
 
 /// <summary>
 
 /// 处理CONNECT命令,此处作用是支持QQ,MSN,以及多级代理串联等
 
 /// </summary>
 
 /// <param name="RawUrl"></param>
 
 private void DoConnect( string RawUrl )
 
 {
 
 string[] Args = RawUrl.Split( ':' );
 
 
 
 string Host = Args[0];
 
 int Port = int.Parse(Args[1]);
 
 
 
 Socket ServerSocket = null;
 
 try
 
 {
 
 IPAddress[] IpList = Dns.GetHostEntry(Host).AddressList;
 
 Console.WriteLine("尝试连接:", IpList[0], Port);
 
 
 
 ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 
 ServerSocket.Connect(IpList[0], Port);
 
 }
 
 catch (Exception e)
 
 {
 
 Console.WriteLine("连接真实服务器异常: " + e.Message);
 
 }
 
 
 
 // 连接真实服务器成功
 
 if (ServerSocket.Connected)
 
 {
 
 ClientSocket.Send( ASCII.GetBytes("HTTP/0 200 Connection establishedrnrn") );
 
 }
 
 else
 
 {
 
 ClientSocket.Shutdown(SocketShutdown.Both);
 
 ClientSocket.Close();
 
 }
 
 
 
 // 开始转发数据
 
 ForwardTcpData(ClientSocket, ServerSocket);
 
 }

[1] [2] [3] 下一页

责任编辑:朱倩  联系方式  Email:朱倩
电话:51228163
  • 上一篇编程:

  • 下一篇编程:
  • (只显示最新5条。评论内容只代表网友观点,与本站立场无关!)
    姓 名:
    * 游客填写  ·注册用户
    主 页:
    评 分:
    1分 2分 3分 4分 5分
    评论内容:
    验证码: *
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  • 最新hack更新
    最新推荐资讯
    相关编程
    给初学编程者的忠告
    C#版QQ机器人组件源码
    给初学编程者的忠告
    给初学编程者的忠告
    C#中英文混合朗读代码
    C#中get和set访问器的解释
    用C#进行Visio二次开发
    C# 中的关键字base、this
     3.0的五项主要改进
    用Visual C#开发简单的复合控件
    最新会员软件
    最新推荐视频
    最新推荐动画

    Copyright @ 2005 77169.Net Inc. All rights reserved. 华夏黑客同盟 版权所有
    北京市电信通提供网络带宽

    mailto:webmaster@77169.net
    咨询QQ号:836982 / 59280880
    联系站长 QQ38588913
    热线电话: 86-10-67634029/676229433
    京ICP证041431号