关于C#使用socks5做代理

在实际使用的过程中可能存在使用代理访问其他网站,以防因过度频繁访问,自己ip被封,如下提供C#使用socks5的大致代码,个人可以根据实际情况进行封装、加工。切勿乱用保密

 public class LoadProxyHelper
    {
        private static readonly log4net.ILog _logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        // 默认使用array 可以根据自己的爱好调整
        private static string[] ipdatas = new string[20];
// 如下代理ip未必可用,请自行找寻(本次只是作为一个样本)
        private static string ipFormat = "x.x.x.{0}";
        static LoadProxyHelper()
        {
            // 给的是固定的ip
            for (int i = 0; i < ipdatas.Length; i++)
            {
                ipdatas[i] = string.Format(ipFormat , 19+i);
            }
        }

        public bool m_RequireAuthorize = false;
        public string m_user = string.Empty;
        public string m_pass = string.Empty;
        public byte[] bytes  = new byte[1024];

        /// <summary>
        /// 设定byte
        /// </summary>
        public byte[] RequireBytes
        {
            get { return bytes; }
            set { bytes = value; }
        }
        /// <summary>
        /// default is false
        /// </summary>
        public bool RequireAuthorize
        {
            get { return m_RequireAuthorize; }
            set { m_RequireAuthorize = value; }
        }
        public string Username
        {
            get { return m_pass; }
            set { m_pass = value; }
        }
        public string Password
        {
            get { return m_user; }
            set { m_user = value; }
        }

        private static string GetEncodType(string ContentType)
        {
            string strTemp = string.Empty;
            strTemp = ContentType;
            if (strTemp != null && strTemp.IndexOf("charset") > -1)
            {
                int index = strTemp.IndexOf("charset=") + 8;
                strTemp = strTemp.Substring(index, strTemp.Length - index);
                return strTemp;
            }
            return Encoding.Default.BodyName;
        }
        /// <summary>
        /// 获取请求返回的结果
        /// 注意包头中的每一个内容后面不能缺失“\r\n”
        /// 同时注意targetHost需要为域名 
        /// </summary>
        /// <returns></returns>
        public string GetSocketBytes(string targetHost,int targetPort,string request,string encode,string refer="")
        {
            try
            {
                string messages = string.Empty;
                int rl = 0;
                string sr = string.Empty;

                Random rand = new Random();
                string ip = ipdatas[rand.Next(0, 20)];
                Socket sRH = GetSocket(ip, 8080);
                ConnectProxyServer(targetHost, targetPort, sRH);
                SocketSend(request + "\r\n", sRH);
                SocketSend("Accept-Language:zh-CN,zh;q=0.8\r\n", sRH);
                SocketSend("Connection:close\r\n", sRH);
                SocketSend(string.Format("Host:{0}\r\n", targetHost), sRH);
                SocketSend("User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36\r\n", sRH);
                SocketSend("\r\n", sRH);

                rl = sRH.Receive(bytes);
               sr = Encoding.GetEncoding(GetEncodType(encode)).GetString(bytes, 0, rl);
                //sr = GetResponseByEncode(encode, rl);

                StringBuilder messDatas = new StringBuilder();

                while (sr.Length > 0)
                {
                    rl = sRH.Receive(bytes);
                    //sr = GetResponseByEncode(encode, rl);
                    sr = Encoding.GetEncoding(GetEncodType(encode)).GetString(bytes, 0, rl);
                    messDatas.Append(sr);
                    Console.WriteLine(sr);
                }
                if (!string.IsNullOrWhiteSpace(messDatas.ToString()))
                {
                    messages = messDatas.ToString();
                }

                return messages;
            }
            catch(Exception ex)
            {
                StringBuilder sblog = new StringBuilder();
                sblog.AppendFormat("{0}异常信息( GetSocketBytes ):", "LoadProxyHelper");
                sblog.AppendFormat("{0}ex:{1},", Environment.NewLine, ex.ToString());
                sblog.AppendFormat("{0}StackTrace:{1},", Environment.NewLine, ex.StackTrace.ToString());
                _logger.Fatal(sblog.ToString(), ex);
            }
            return "";
        }

        /// <summary>
        /// 获取response内容
        /// </summary>
        /// <param name="encode"></param>
        /// <param name="rl"></param>
        /// <returns></returns>
        private string GetResponseByEncode(string encode,int rl)
        {
            string sr = string.Empty;
            switch (encode)
            {
                case "utf-8":
                    sr = Encoding.UTF8.GetString(bytes, 0, rl);
                    break;
                case "ascii":
                    sr = Encoding.ASCII.GetString(bytes, 0, rl);
                    break;
                case "unicode":
                    sr = Encoding.Unicode.GetString(bytes, 0, rl);
                    break;
                default:
                    sr = Encoding.Default.GetString(bytes, 0, rl);
                    break;
            }
            return sr;
        }

        /// <summary>
        /// 发送请求
        /// </summary>
        /// <param name="str"></param>
        /// <param name="sRH"></param>
        private void SocketSend(string str, Socket sRH)
        {
            try
            {
                byte[] b = Encoding.Default.GetBytes(str);
                sRH.Send(b);
            }
            catch (Exception ex)
            {
                StringBuilder sblog = new StringBuilder();
                sblog.AppendFormat("{0}异常信息( SocketSend ):", "LoadProxyHelper");
                sblog.AppendFormat("{0}ex:{1},", Environment.NewLine, ex.ToString());
                sblog.AppendFormat("{0}StackTrace:{1},", Environment.NewLine, ex.StackTrace.ToString());
                _logger.Fatal(sblog.ToString(), ex);
            }
        }

        /// <summary>
        /// 连接代理服务器
        /// </summary>
        /// <param name="strRemoteHost"></param>
        /// <param name="iRemotePort"></param>
        /// <param name="sProxyServer"></param>
        /// <returns></returns>
        public bool ConnectProxyServer(string strRemoteHost, int iRemotePort, Socket sProxyServer)
        {
            try
            {
                //构造Socks5代理服务器第一连接头(无用户名密码) 
                byte[] bySock5Send = new Byte[10];
                bySock5Send[0] = 5;
                bySock5Send[1] = 1;
                bySock5Send[2] = RequireAuthorize ? (byte)2 : (byte)0;

                //发送Socks5代理第一次连接信息 
                sProxyServer.Send(bySock5Send, 3, SocketFlags.None);

                byte[] bySock5Receive = new byte[10];

                int iRecCount = sProxyServer.Receive(bySock5Receive, bySock5Receive.Length, SocketFlags.None);


                //用户验证
                if (bySock5Receive[1] == 2 && !RequireAuthorize)
                {
                    throw new Exception("代理服务器需要进行身份确认。");
                }
                else if (bySock5Receive[1] == 2)
                {
                    //构造Socks5代理服务器第一连接头(无用户名密码)
                    byte[] bUser = Encoding.Default.GetBytes(Username);
                    byte[] bPass = Encoding.Default.GetBytes(Password);

                    int dl = 3 + bUser.Length + bPass.Length;

                    bySock5Send = new Byte[dl];
                    bySock5Send[0] = 5;
                    bySock5Send[1] = (byte)bUser.Length;
                    Array.Copy(bUser, 0, bySock5Send, 2, bUser.Length);
                    bySock5Send[2 + bUser.Length] = (byte)bPass.Length;
                    Array.Copy(bPass, 0, bySock5Send, 3 + bUser.Length, bPass.Length);

                    //发送Socks5代理第一次连接信息 
                    sProxyServer.Send(bySock5Send, dl, SocketFlags.None);

                    bySock5Receive = new byte[100];
                    iRecCount = sProxyServer.Receive(bySock5Receive, bySock5Receive.Length, SocketFlags.None);
                }

                if (iRecCount < 2)
                {
                    sProxyServer.Close();
                    throw new Exception("不能获得代理服务器正确响应。");
                }

                if (bySock5Receive[0] != 5 || (bySock5Receive[1] != 0 && bySock5Receive[1] != 2))
                {
                    sProxyServer.Close();
                    throw new Exception("代理服务其返回的响应错误。");
                }

                if (bySock5Receive[1] == 0)
                {
                    bySock5Send[0] = 5;
                    bySock5Send[1] = 1;
                    bySock5Send[2] = 0;
                    bySock5Send[3] = 1;

                    IPAddress ipAdd = Dns.Resolve(strRemoteHost).AddressList[0];
                    string strIp = ipAdd.ToString();
                    string[] strAryTemp = strIp.Split(new char[] { '.' });
                    bySock5Send[4] = Convert.ToByte(strAryTemp[0]);
                    bySock5Send[5] = Convert.ToByte(strAryTemp[1]);
                    bySock5Send[6] = Convert.ToByte(strAryTemp[2]);
                    bySock5Send[7] = Convert.ToByte(strAryTemp[3]);

                    bySock5Send[8] = (byte)(iRemotePort / 256);
                    bySock5Send[9] = (byte)(iRemotePort % 256);

                    sProxyServer.Send(bySock5Send, bySock5Send.Length, SocketFlags.None);
                    iRecCount = sProxyServer.Receive(bySock5Receive, bySock5Receive.Length, SocketFlags.None);

                    if (bySock5Receive[0] != 5 || bySock5Receive[1] != 0)
                    {
                        sProxyServer.Close();
                        throw new Exception("第二次连接Socks5代理返回数据出错。");
                    }
                    return true;
                }

                else
                {
                    if (bySock5Receive[1] == 2)
                        throw new Exception("代理服务器需要进行身份确认。");
                    else
                        return false;
                }
            }
            catch(Exception ex)
            {
                StringBuilder sblog = new StringBuilder();
                sblog.AppendFormat("{0}异常信息( ConnectProxyServer ):", "LoadProxyHelper");
                sblog.AppendFormat("{0}ex:{1},", Environment.NewLine, ex.ToString());
                sblog.AppendFormat("{0}StackTrace:{1},", Environment.NewLine, ex.StackTrace.ToString());
                _logger.Fatal(sblog.ToString(), ex);
            }
            return false;
        }

        /// <summary>
        /// 获取连接的socket
        /// </summary>
        /// <param name="strIpAdd"></param>
        /// <param name="iPort"></param>
        /// <returns></returns>
        public Socket GetSocket(string strIpAdd, int iPort)
        {
            try
            {
                IPAddress hostadd = IPAddress.Parse(strIpAdd);//Dns.Resolve(strIpAdd).AddressList[0];
                IPEndPoint EPhost = new IPEndPoint(hostadd, iPort);
                Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                s.Connect(EPhost);
                return s;
            }
            catch (Exception ex)
            {
                StringBuilder sblog = new StringBuilder();
                sblog.AppendFormat("{0}异常信息( GetSocket ):", "LoadProxyHelper");
                sblog.AppendFormat("{0}ex:{1},", Environment.NewLine, ex.ToString());
                sblog.AppendFormat("{0}StackTrace:{1},", Environment.NewLine, ex.StackTrace.ToString());
                _logger.Fatal(sblog.ToString(), ex);
                throw (ex);
            }
        }
    }

 调用代码

 

string host = "www.baidu.com";
string encode = "UTF-8";
string requset = string.Format("GET / HTTP/1.1");
// socks5
strReceiveString = proxHelper.GetSocketBytes(host, 80, requset, encode);
根据实际情况填写

 关于socks5发送请求的包头,请参考附件图片自行添加或修改

如上基本上实现一个通过C#+socks5完成代理操作

关于socks5说明请参阅:http://www.cnblogs.com/zhujiechang/archive/2008/10/21/1316308.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值