You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中通过代理连接ClientWebSocket失败问题(安卓与iOS)

Unity中ClientWebSocket通过代理连接失败的排查与解决

问题描述

我正尝试在Unity中通过代理配置使用ClientWebSocket连接WebSocket服务器,代码如下:

var source = new CancellationTokenSource();
var token = source.Token;

var socket = new ClientWebSocket();
WebRequest.DefaultWebProxy = new WebProxy(proxyUrl, false); // 尝试设置DefaultWebProxy也没用
socket.Options.Proxy = new WebProxy(proxyUrl, false);
                
await socket.ConnectAsync(uri, token);

运行时抛出Unable to connect to the remote server错误,堆栈跟踪如下:

11-10 14:16:41.013 I/Unity (12692): !!! System.Net.WebSockets.WebSocketException (0x80004005): Unable to connect to the remote server ---> System.Net.Sockets.SocketException (0x80004005): mono-io-layer-error (111)
11-10 14:16:41.013 I/Unity (12692): at System.Net.Sockets.SocketAsyncResult.CheckIfThrowDelayedException () [0x00000] in <00000000000000000000000000000000>:0 
11-10 14:16:41.013 I/Unity (12692): at System.Net.Sockets.Socket.EndConnect (System.IAsyncResult asyncResult) [0x00000] in <00000000000000000000000000000000>:0 
11-10 14:16:41.013 I/Unity (12692): at System.Net.Sockets.Socket+<>c.<ConnectAsync>b__10_0 (System.IAsyncResult iar) [0x00000] in <00000000000000000000000000000000>:0 
11-10 14:16:41.013 I/Unity (12692): at System.Net.Sockets.SocketAsyncResult+<>c.<Complete>b__27_0 (System.Object state) [0x00000] in <00000000000000000000000000000000>:0 
11-10 14:16:41.013 I/Unity (12692): at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () [0x00000] in <00000000000000000000000000000000>:0 
11-10 14:16:41.013 I/Unity (12692): at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00000] in <00000000000000000000000000000000>:0 
11-10 14:16:41.013 I/Unity (12692): at System.Threading._ThreadPoolWaitCallback.PerformWaitCallb

另外,使用HttpWebRequest配置相同代理能成功发起请求:

HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
WebRequest.DefaultWebProxy = new WebProxy(proxyUrl, false);
request.Proxy = new WebProxy(proxyUrl, false);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
response.Close();

尝试自定义实现IWebProxy接口,但GetProxy和IsBypassed方法从未被调用:

public class WebSocketProxy : IWebProxy
{
    private ICredentials iCredentials;
    private Uri webProxyUri;

    public WebSocketProxy(Uri proxyUri)
    {
        webProxyUri = proxyUri;
    }

    public ICredentials Credentials
    {
        get
        {
            return iCredentials;
        }
        set
        {
            if (iCredentials != value)
            {
                iCredentials = value;
            }
        }
    }

    public Uri? GetProxy(Uri destUri)
    {
        // Always use the same proxy.
        Debug.Log("GetProxy called");
        return webProxyUri;
    }

    public bool IsBypassed(Uri hostUri)
    {
        // Never bypass the proxy.
        Debug.Log("IsBypassed called");
        return false;
    }
}

可能的原因与解决方法

1. ClientWebSocket仅支持SOCKS代理(不支持HTTP代理)

Unity使用的Mono版本中,ClientWebSocket的Proxy配置仅对SOCKS代理生效。HTTP代理能在HttpWebRequest中工作,是因为HTTP请求本身支持通过代理转发,但WebSocket需要先建立TCP隧道,默认的ClientWebSocket不会自动处理HTTP代理的隧道逻辑,导致连接被拒绝(错误码111即连接被拒绝)。

解决方法:手动实现HTTP代理隧道
先向代理发送CONNECT请求建立TCP隧道,再在隧道上进行WebSocket握手:

// 1. 与代理建立TCP连接
var proxyUri = new Uri(proxyUrl);
var proxyTcpClient = new TcpClient();
await proxyTcpClient.ConnectAsync(proxyUri.Host, proxyUri.Port);

// 2. 发送CONNECT请求创建隧道
var connectRequest = $"CONNECT {uri.Host}:{uri.Port} HTTP/1.1\r\nHost: {uri.Host}:{uri.Port}\r\n\r\n";
var requestBuffer = Encoding.ASCII.GetBytes(connectRequest);
await proxyTcpClient.GetStream().WriteAsync(requestBuffer, 0, requestBuffer.Length);

// 3. 验证代理响应,确认隧道建立成功
var responseBuffer = new byte[1024];
var readLength = await proxyTcpClient.GetStream().ReadAsync(responseBuffer, 0, responseBuffer.Length);
var proxyResponse = Encoding.ASCII.GetString(responseBuffer, 0, readLength);
if (!proxyResponse.StartsWith("HTTP/1.1 200"))
{
    throw new Exception("代理隧道建立失败");
}

// 4. 使用已建立的隧道连接WebSocket服务器
var socket = new ClientWebSocket();
await socket.ConnectAsync(uri, CancellationToken.None, proxyTcpClient.GetStream());

2. 代理地址解析异常

即使HttpWebRequest能正常解析proxyUrl,ClientWebSocket的代理解析逻辑可能存在差异,比如URL格式不兼容。

解决方法:手动拆分代理主机和端口

var proxyUri = new Uri(proxyUrl);
var proxy = new WebProxy(proxyUri.Host, proxyUri.Port);
socket.Options.Proxy = proxy;

3. 移动端网络权限缺失

从日志看是Android环境,需确保应用具备网络访问权限:

  • 检查Unity PlayerSettings > Android > Other Settings > Internet Access设置为Require;
  • 确认AndroidManifest.xml中包含<uses-permission android:name="android.permission.INTERNET" />权限。

4. 自定义IWebProxy未生效的原因

Unity的ClientWebSocket底层未实现IWebProxy的调用逻辑,仅依赖系统代理或特定类型的代理配置,因此自定义的IWebProxy方法不会被触发,无需继续尝试该方案。

内容的提问来源于stack exchange,提问作者Robert-96

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 15:23:14