C#连接socket代理并转发消息

sock代理工作原理大致如下:
1。[需要代理方]向服务器发出请求信息;
2。[代理方]应答;
3。[需要代理方]接到应答后发送向[代理方]发送目的ip和端口;
4。[代理方]与目的连接;
5。[代理方]将[需要代理方]发出的信息传到目的方,将目的方发出的信息传到[需要代理方];
6。代理完成。

sock4的TCP代理工作流程:
1。我们首先还是连接服务器,然后发送数据给服务器。由于是无用户密码验证,我们需要发送9个字节的数据,展开写为 04 01 + 目标端口(2字节) + 目标IP(4字节) + 00,其中目标端口和目标IP就是我们真正要连接的服务器端口和服务器地址;
2。代理服务器返回8字节的数据,我们只要判断第二字节是否为90即可,若是90连接成功,否则失败.剩下的操作和不存在代理服务器一样,可直接用发送\接受数据。

1 通过端口号连接代理服务器

 System.Net.Sockets.Socket VSocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
VSocket..Connect(_proxyHost, _proxyPort);

2 发送字节数据给服务器验证,这里是socket4连接,返回第二字节为90代表连接成功

  internal virtual void SendCommand(NetworkStream proxy, byte command, string destinationHost, int destinationPort, string userId)
        {
            if (userId == null)
                userId = "";

            byte[] destIp = GetIPAddressBytes(destinationHost);
            byte[] destPort = GetDestinationPortBytes(destinationPort);
            byte[] userIdBytes = ASCIIEncoding.ASCII.GetBytes(userId);
            byte[] request = new byte[9 + userIdBytes.Length];

            //  set the bits on the request byte array
            request[0] = SOCKS4_VERSION_NUMBER;
            request[1] = command;
            destPort.CopyTo(request, 2);
            destIp.CopyTo(request, 4);
            userIdBytes.CopyTo(request, 8);
            request[8 + userIdBytes.Length] = 0x00;  // null (byte with all zeros) terminator for userId

            // send the connect request
            proxy.Write(request, 0, request.Length);
           
            // wait for the proxy server to respond
            WaitForData(proxy);


            byte[] response = new byte[8];

            // read the resonse from the network stream
            proxy.Read(response, 0, 8);

            //  evaluate the reply code for an error condition
            if (response[1] != SOCKS4_CMD_REPLY_REQUEST_GRANTED)
                HandleProxyCommandError(response, destinationHost, destinationPort);
        }

3 组装http请求头发送给代理服务器。

var str="GET http://10.100.110.144/ HTTP/1.1\r\nAccept: text/html, application/xhtml+xml, */*\r\nAccept-Language: zh-CN\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko\r\nAccept-Encoding: gzip, deflate\r\nHost: 10.100.110.144\r\nDNT: 1\r\nProxy-Connection: Keep-Alive\r\n\r\n"
  VSocket.Send(str);

4 获取返回信息

      Restr = Receive(VSocket);
     private string Receive(Socket socketSend)
        {
            string str = "";
            while (true)
            {
                byte[] buffer = new byte[10000];
                //实际接收到的字节数
                int r = socketSend.Receive(buffer); 
                str+= Encoding.Default.GetString(buffer, 0, r - 1);
                if (r< 10000)
                {
                    break;
                }
            }
            return str;

        }

这样很浪费性能,换下面这种写法

        private string Receive(Socket socketSend)
        { 
            string recvStr = "";
            byte[] recvBytes = new byte[1024];
            int bytes;
            do
            {
                bytes = socketSend.Receive(recvBytes, recvBytes.Length, 0); //从客户端接受消息
                recvStr += Encoding.UTF8.GetString(recvBytes, 0, bytes);   //指定接收到的字节转换为字符串
            } while (bytes == 1024); 
            return recvStr; 
        }

1  在循环外面声明数组接收数据

2 用收到数组长度来转化为字符串

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值