You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C#简易HTTP代理无法接收安卓手机请求的问题求助

排查C# HTTP代理未收到手机请求的问题

结合你的场景和代码,我梳理了几个最可能的原因和对应的解决方法:

1. HttpListener 前缀绑定或权限问题

你的代码里用了http://*:7777/作为监听前缀,这里可能存在两个问题:

  • 权限不足:在Windows系统中,非管理员身份运行程序时,绑定*或特定IP的端口可能需要额外的URL ACL权限。如果你的程序启动时没有报错,但实际没监听端口,尝试以管理员身份运行程序
  • 前缀绑定范围*理论上监听所有网络接口,但有些环境下可能没有正确绑定到局域网IP。你可以把前缀改成明确的局域网IP:
    listener.Prefixes.Add("http://192.1.1.24:7777/");
    
    这样能确保程序只监听你的电脑局域网IP的7777端口,避免监听范围的歧义。

2. 手机代理设置的细节问题

即使你填了IP和端口,也可能有这些疏漏:

  • 代理类型错误:确保手机设置的是HTTP代理,而非HTTPS代理(你的代码目前只处理HTTP请求,HTTPS需要额外处理CONNECT方法)。
  • APP绕过系统代理:部分APP(比如某些浏览器、社交软件)默认会绕过系统代理,你可以先测试用手机自带浏览器访问一个纯HTTP网站(比如http://example.com),看代理是否能收到请求。
  • 网络连通性验证:先在手机上ping你的电脑IP(192.1.1.24),确认两台设备确实能互相访问。如果ping不通,说明网络层面还有问题,比如路由器的隔离设置。

3. 代码未处理HTTPS的CONNECT请求

现在绝大多数网站都是HTTPS,当手机访问HTTPS网站时,会先发送CONNECT请求到代理服务器,而你的代码完全没有处理这种请求类型。这会导致:

  • 手机发送CONNECT请求后,代理没有响应,手机会认为代理不可用,进而停止发送后续请求。
  • 你在控制台看不到任何请求日志,因为代码里只处理了普通的HTTP GET/POST等请求。

要解决这个问题,你需要在ProcessRequest方法中先判断请求类型,添加CONNECT请求的处理逻辑:

public void ProcessRequest()
{
    var request = originalContext.Request;
    // 处理CONNECT请求(HTTPS代理需要)
    if (request.HttpMethod == "CONNECT")
    {
        HandleConnectRequest(request);
        return;
    }

    // 原有HTTP请求处理逻辑
    string rawUrl = request.RawUrl;
    ConsoleUtilities.WriteRequest("Proxy receive a request for: " + rawUrl);
    var relayRequest = (HttpWebRequest) WebRequest.Create(rawUrl);
    relayRequest.KeepAlive = false;
    relayRequest.Proxy.Credentials = CredentialCache.DefaultCredentials;
    relayRequest.UserAgent = this.originalContext.Request.UserAgent;
    var requestData = new RequestState(relayRequest, originalContext);
    relayRequest.BeginGetResponse(ResponseCallBack, requestData);
}

private void HandleConnectRequest(HttpListenerRequest request)
{
    var response = originalContext.Response;
    try
    {
        // 解析目标主机和端口,比如CONNECT example.com:443 HTTP/1.1
        var hostPort = request.Url.AbsolutePath.Split(':');
        string host = hostPort[0];
        int port = int.Parse(hostPort[1]);

        // 建立到目标服务器的TCP连接
        using (var client = new System.Net.Sockets.TcpClient(host, port))
        using (var stream = client.GetStream())
        {
            // 向客户端返回200连接建立响应
            response.StatusCode = (int)HttpStatusCode.OK;
            response.ContentLength64 = 0;
            response.OutputStream.Close();

            // 开始双向转发数据
            var clientStream = originalContext.Request.InputStream;
            var buffer = new byte[4096];
            int bytesRead;
            
            // 从客户端读,转发到目标服务器
            while ((bytesRead = clientStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                stream.Write(buffer, 0, bytesRead);
            }
            // 从目标服务器读,转发到客户端
            while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
            {
                originalContext.Response.OutputStream.Write(buffer, 0, bytesRead);
            }
        }
    }
    catch (Exception ex)
    {
        response.StatusCode = (int)HttpStatusCode.BadGateway;
        response.OutputStream.Close();
        Console.WriteLine("处理CONNECT请求出错: " + ex.Message);
    }
    finally
    {
        response.Close();
    }
}

这段代码会处理CONNECT请求,建立TCP隧道,让HTTPS流量能正常通过代理。

4. 监听端口未正确开放

虽然你说防火墙没拦截,但可以再用命令确认端口状态:

  • 在电脑上打开命令提示符,输入:netstat -ano | findstr 7777
  • 如果输出里有0.0.0.0:7777192.1.1.24:7777的监听记录,说明端口正常监听;如果只有127.0.0.1:7777,那程序只监听了本地回环,手机肯定连不上。

内容的提问来源于stack exchange,提问作者jakob

火山引擎 最新活动