Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将代理与TcpClient.ConnectAsync()一起使用?_C#_.net_Networking_Proxy_Tcpclient - Fatal编程技术网

C# 如何将代理与TcpClient.ConnectAsync()一起使用?

C# 如何将代理与TcpClient.ConnectAsync()一起使用?,c#,.net,networking,proxy,tcpclient,C#,.net,Networking,Proxy,Tcpclient,NET中的HTTP代理支持实际上不支持较低级别的类,如TcpClient或Socket。但我想通过支持“connect”命令的HTTP代理连接TCPServer(ip、端口) 因此,我需要执行以下步骤: 连接到代理服务器 发送连接主机:端口HTTP/1.1 发送 等待回应。如果它包含HTTP/1.X 200,则连接成功 进一步阅读响应行,直到收到空行 它通过代理连接到外部世界。任何可能与代理进行的数据交换 事实上,我是在没有代理的情况下做这件事的 TcpClient _client;

NET中的HTTP代理支持实际上不支持较低级别的类,如TcpClient或Socket。但我想通过支持“connect”命令的HTTP代理连接TCPServer(ip、端口)

因此,我需要执行以下步骤:

  • 连接到代理服务器
  • 发送
    连接主机:端口HTTP/1.1
  • 发送
  • 等待回应。如果它包含
    HTTP/1.X 200
    ,则连接成功
  • 进一步阅读响应行,直到收到空行
  • 它通过代理连接到外部世界。任何可能与代理进行的数据交换
  • 事实上,我是在没有代理的情况下做这件事的

        TcpClient _client;
        NetworkStream _stream;
    
        public static async Task<bool> ConnectAsync(string hostname, int port)
        {
            _client = new TcpClient();
            await _client.ConnectAsync(hostname, port).ConfigureAwait(false);
            _stream = conn._client.GetStream();
    
            ..... Do some stuff
    
            // Connexion OK
            return true;
        }
    
    TcpClient\u客户端;
    网络流(NetworkStream);;
    公共静态异步任务ConnectAsync(字符串主机名,int端口)
    {
    _client=新的TcpClient();
    await\u client.ConnectAsync(主机名、端口)。ConfigureAwait(false);
    _stream=conn._client.GetStream();
    ……做点什么
    //连接正常
    返回true;
    }
    
    如何在连接TcpClient之前使用代理和凭据?

    我找到了一个基于和的解决方案

    TcpClient\u客户端;
    网络流(NetworkStream);;
    公共TcpClient ProxyTcpClient(字符串targetHost、int targetPort、字符串httpProxyHost、int httpProxyPort、字符串proxyUserName、字符串proxyPassword)
    {
    const BindingFlags Flags=BindingFlags.NonPublic | BindingFlags.Instance;
    Uri proxyUri=新的UriBuilder
    {
    Scheme=Uri.UriSchemeHttp,
    主机=httpProxyHost,
    端口=httpProxyPort
    }.Uri;
    Uri targetUri=新的UriBuilder
    {
    Scheme=Uri.UriSchemeHttp,
    主机=目标主机,
    端口=目标端口
    }.Uri;
    WebProxy WebProxy=新的WebProxy(proxyUri,true);
    webProxy.Credentials=新的网络凭据(代理用户名、代理密码);
    WebRequest=WebRequest.Create(targetUri);
    Proxy=webProxy;
    request.Method=“CONNECT”;
    HttpWebResponse=(HttpWebResponse)request.GetResponse();
    Stream responseStream=response.GetResponseStream();
    类型responseType=responseStream.GetType();
    PropertyInfo connectionProperty=responseType.GetProperty(“连接”,标志);
    var connection=connectionProperty.GetValue(responseStream,null);
    类型connectionType=connection.GetType();
    PropertyInfo networkStreamProperty=connectionType.GetProperty(“NetworkStream”,标志);
    NetworkStream NetworkStream=(NetworkStream)networkStreamProperty.GetValue(connection,null);
    类型nsType=networkStream.GetType();
    PropertyInfo-socketProperty=nsType.GetProperty(“套接字”,标志);
    Socket套接字=(Socket)socketProperty.GetValue(networkStream,null);
    返回新的TcpClient{Client=socket};
    }
    公共静态异步任务ConnectAsync(字符串主机名,int端口)
    {
    _client=ProxyTcpClient(“IPTargetHost”,1234,“IPProxyHost”,5678,“Userproxy”,“Userppwd”);
    _stream=conn._client.GetStream();
    ……做点什么
    //连接正常
    返回true;
    }
    
    我们已经设法使用.Net的
    套接字实现了它。调用Nuget包。代码非常简单:

    public static TcpClient CreateProxied(Uri proxy, Uri destination)
    {
        var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
        socket.Connect(proxy.Host, proxy.Port);
    
        var connectMessage = Encoding.UTF8.GetBytes($"CONNECT {destination.Host}:{destination.Port} HTTP/1.1{Environment.NewLine}{Environment.NewLine}");
        socket.Send(connectMessage);
    
        byte[] receiveBuffer = new byte[1024];
        var received = socket.Receive(receiveBuffer);
    
        var response = ASCIIEncoding.ASCII.GetString(receiveBuffer, 0, received);
    
        if (!response.Contains("200 OK"))
        {
            throw new Exception($"Error connecting to proxy server {destination.Host}:{destination.Port}. Response: {response}");
        }
    
        return new TcpClient
        {
            Client = socket
        };
    }
    
    此处投稿:

    若代理需要基本身份验证,则要扩展答案,请将标题添加到连接消息中

    var auth = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{proxy.Login}:{proxy.Password}"));
    var connectMessage = Encoding.UTF8.GetBytes($"CONNECT {host}:{port} HTTP/1.1\nProxy-Authorization: Basic {auth}\n\n");
    socket.Send(connectMessage);
    

    这个解决方案似乎有点黑。。。有没有其他方法可以在不使用反射的情况下设置代理?
    var auth = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{proxy.Login}:{proxy.Password}"));
    var connectMessage = Encoding.UTF8.GetBytes($"CONNECT {host}:{port} HTTP/1.1\nProxy-Authorization: Basic {auth}\n\n");
    socket.Send(connectMessage);