为了账号安全,请及时绑定邮箱和手机立即绑定

简单实现Http代理工具

标签:
架构

本来意图是想写个工具放到服务器里代理一下上秋秋的。

没想到N台(电信/联通/移动)的服务器都把端口全封了。

所以以下代码是在本地测试代理网页访问通过。

 

说下思路再上代码及下载:

其实一句话就是:产生两个Soket,一个负责接收请求和回发请求,另一个负责中转的去请求和接收。

重点一句话就是:每个请求产生一个线程处理,处理时关键是的延时处理(不然数据接收不全)。

 

现在上代码,Proxy自定义类:

 

Proxy

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;//by 路过秋天
namespace TCPProxy
{
    public class Proxy
    {
        Socket clientSocket;//接收和返回
        Byte[] read = null;//存储来自客户端请求数据包
        Byte[] recvBytes = null;//存储中转请求返回的数据

        public Proxy(Socket socket)
        {
            clientSocket = socket;
            recvBytes = new Byte[1024 * 1024];
            clientSocket.ReceiveBufferSize = recvBytes.Length;
            clientSocket.SendBufferSize = recvBytes.Length;
            clientSocket.SendTimeout = 10000;
            clientSocket.ReceiveTimeout = 10000;
        }
        public void Run()
        {
            #region 获取客户端请求数据
            string clientmessage = "";
            read = new byte[clientSocket.Available];
            int bytes = ReadMessage(read, ref clientSocket, ref clientmessage);
            if (bytes == 0)
            {
                Write("读取不到数据!");
                clientSocket.Shutdown(SocketShutdown.Both);
                clientSocket.Close();
                return;
            }
            int port = 80;
            string url = GetUrl(clientmessage, port);
            #endregion
            
            try
            {
                #region IP解析获取
                IPHostEntry IPHost= Dns.GetHostEntry(url);
                Write("-----------------------------请求开始---------------------------");
                Write("http://" + IPHost.HostName);
                string[] aliases = IPHost.Aliases;
                IPAddress[] address = IPHost.AddressList;//解析出要访问的服务器地址
                Write("IP地址:" + address[0]);
                #endregion
               

                #region 创建中转Socket及建立连接
                IPEndPoint ipEndpoint = new IPEndPoint(address[0], port);
                Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //创建连接Web服务器端的Socket对象
                IPsocket.Connect(ipEndpoint);
                //Socket连Web接服务器
                if (IPsocket.Connected)
                {
                    Write("Socket 正确连接!");
                }
                #endregion
                #region 发送中转请求
                IPsocket.Send(read, 0);
                Write("发送字节:" + read.Length);
                #endregion
                #region 接收中转请求数据
                int length = 0, count = 0;
                do
                {
                    length = IPsocket.Receive(recvBytes, count, IPsocket.Available, 0);
                    count = count + length;
                    Write("正在接收数据..." + length);
                    System.Threading.Thread.Sleep(100);//关键点,请求太快数据接收不全
                }
                while (IPsocket.Available > 0);
                #endregion
                #region 关闭中转请求Socket
                IPsocket.Shutdown(SocketShutdown.Both);
                IPsocket.Close();
                #endregion

                #region 将中转请求收到的数据发回客户端
                clientSocket.Send(recvBytes, 0, count, 0);
                Write("正在返回数据..." + count);
                #endregion
                #region 结束请求,关闭客户端Socket
                clientSocket.Shutdown(SocketShutdown.Both);
                clientSocket.Close();
                recvBytes = null;
                Write("完成,已关闭连接...");
                Write("-----------------------------请求结束---------------------------");
                #endregion
            }
            catch (Exception err)
            {
                System.Console.WriteLine(err.Message + err.Source);
            }

        }
        //从请求头里解析出url和端口号
        private string GetUrl(string clientmessage, int port)
        {
            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).Trim();

            string url = string.Empty;
            if (!part1.Contains("http://"))
            {
                part1 = "http://" + part1;
            }
            Uri uri = new Uri(part1);
            url = uri.Host;
            port = uri.Port;
            return url;
        }
        //接收客户端的HTTP请求数据
        private int ReadMessage(byte[] readByte, ref Socket s, ref string clientmessage)
        {
            int bytes = s.Receive(readByte, readByte.Length, 0);
            clientmessage = Encoding.ASCII.GetString(readByte);
            return bytes;
        }

        private void Write(string msg)
        {
            // return;
            System.Console.WriteLine(msg);
        }
    }
}

 

 

在控制台里调用:

 

代码

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Net.Sockets;
using System.Threading;
namespace TCPProxy
{
    class Program
    {
        static void Main(string[] args)
        {
                Listen(8989);
        }
        static void Write(string msg)
        {
            Console.WriteLine(msg);
        }

        static void Listen(int port)
        {
            Write("准备监听端口:" + port);
            TcpListener tcplistener = new TcpListener(port);
            try
            {
                tcplistener.Start();
            }
            catch
            {
                Write("该端口已被占用,请更换端口号!!!");
                ReListen(tcplistener);
            }
            Write("确认:y/n (yes or no):");
            string isOK = Console.ReadLine();
            if (isOK == "y")
            {
                Write("成功监听端口:" + port);
                //侦听端口号 
                Socket socket;
                while (true)
                {
                    socket = tcplistener.AcceptSocket();
                    //并获取传送和接收数据的Scoket实例 
                    Proxy proxy = new Proxy(socket);
                    //Proxy类实例化 
                    Thread thread = new Thread(new ThreadStart(proxy.Run));
                    //创建线程 
                    thread.Start();
                    System.Threading.Thread.Sleep(10);
                    //启动线程 
                }
            }
            else
            {
                ReListen(tcplistener);
            }
        }
        static void ReListen(TcpListener listener)
        {
            if (listener != null)
            {
                listener.Stop();
                listener = null;
            }
            Write("请输入监听端口号:");
            string newPort = Console.ReadLine();
            int port;
            if (int.TryParse(newPort, out port))
            {
                Listen(port);
            }
            else
            {
                ReListen(listener);
            }
        }
    }
}

 

 

本人测试:

在打开IE-》工具->Internet选项->链接->局域网设置->代理连接-》输入IP和端口号

访问网站,查看控制台输出消息,页面访问正常,测试通过。

 

本来想测试下QQ代理,无奈本地已被封,服务器也没端口可用。有空回家再测了。

 

提供代码下载

 

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消