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

Unity TCP客户端Windows正常运行、安卓端(同Wi-Fi网络)无法与服务器通信的问题排查

Unity TCP客户端Windows正常运行、安卓端(同Wi-Fi网络)无法与服务器通信的问题排查

我来帮你一步步拆解这个问题,同Wi-Fi下跨设备的TCP连接踩过的坑还真不少,结合你的代码和场景,咱们从最可能的原因开始排查:


1. 客户端代码的致命错误:手机上连的是自己的IP!

看你的Unity客户端代码,这段逻辑在Windows上能跑纯属巧合:

string hostName = Dns.GetHostName();
IPHostEntry ipHostEntry = Dns.GetHostEntry(hostName);
IPAddress ipAddress = ipHostEntry.AddressList[1];
  • 在Windows上运行Unity时,Dns.GetHostName()获取的是你电脑的主机名,解析后拿到的是电脑的IP,刚好和服务器在同一设备/同网段,所以能连上。
  • 但在手机上运行时,Dns.GetHostName()获取的是手机自己的主机名,解析出来的是手机本地的IP(比如192.168.1.105),你让手机连自己的7777端口,当然找不到你的服务器啊!

解决方法:

把客户端代码里的IP地址改成你电脑的内网IPv4地址(不是127.0.0.1,是同Wi-Fi下的内网IP,比如192.168.1.100这种)。比如:

// 直接替换成你的电脑内网IPv4,先手动写死测试
IPAddress ipAddress = IPAddress.Parse("192.168.1.100");
IPEndPoint endPoint = new IPEndPoint(ipAddress, 7777);

怎么查电脑的内网IP?Windows按Win+R输cmd,然后敲ipconfig,找Wi-Fi模块下的“IPv4地址”就是。


2. 服务器绑定的IP地址不稳定,可能没监听Wi-Fi网卡

你的服务器代码里用了ipHostEntry.AddressList[1],这个列表的顺序是完全不固定的!有时候它是IPv4,有时候是IPv6,有时候是有线网卡的IP,有时候是Wi-Fi的。如果服务器绑定到了有线网卡的IP或者本地回环(127.0.0.1),手机当然连不上。

解决方法:

要么绑定到0.0.0.0(表示监听所有可用网卡的IPv4地址,不管是有线还是Wi-Fi),要么明确获取你的Wi-Fi内网IPv4:

// 方法1:绑定0.0.0.0,最简单可靠
IPAddress ipAddress = IPAddress.Any; // 等价于0.0.0.0
IPEndPoint endPoint = new IPEndPoint(ipAddress, 7777);

或者方法2:遍历AddressList找对应的内网IPv4:

IPAddress ipAddress = null;
foreach (var addr in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{
    // 找IPv4且不是回环地址的
    if (addr.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(addr))
    {
        ipAddress = addr;
        break;
    }
}
if (ipAddress == null)
{
    Console.WriteLine("找不到可用的IPv4地址!");
    return;
}
IPEndPoint endPoint = new IPEndPoint(ipAddress, 7777);

3. Windows防火墙拦截了外部连接请求

这是跨设备连接最容易忽略的点:你在VS里运行的服务器程序,Windows防火墙大概率没允许它接收来自其他设备的连接,手机的请求直接被防火墙挡了。

解决方法:

  1. 临时测试:打开Windows Defender防火墙,暂时关闭(不推荐长期关闭,测试完立刻打开),然后再用手机连一次,如果能连上,就说明是防火墙的问题。
  2. 永久解决:添加防火墙入站规则:
    • 按Win+S搜“Windows Defender防火墙高级设置”
    • 左侧点“入站规则”,右侧点“新建规则”
    • 规则类型选“端口”,下一步
    • 选“TCP”,特定本地端口填7777,下一步
    • 选“允许连接”,下一步
    • 勾选“域”、“专用”(家用Wi-Fi属于专用网络),下一步
    • 给规则起个名字比如“MMORPG Server 7777”,完成。

4. 安卓客户端缺少网络权限

Unity打包安卓时,如果没开启网络权限,应用连不上网络。虽然新版本Unity默认会加,但保险起见确认一下:

  1. 打开Unity的Edit > Project Settings > Player
  2. 切换到Android平台,找到Other Settings里的Permissions
  3. 确保Internet权限是勾选状态;如果没找到,手动添加到Plugins/Android文件夹下的AndroidManifest.xml:
    <uses-permission android:name="android.permission.INTERNET" />
    

5. 安卓主线程阻塞导致连接失败

你的客户端代码是在Start()里同步执行Connect()Send()Receive(),安卓对主线程的阻塞非常敏感,超过几秒就会触发ANR(应用无响应),甚至直接被系统终止操作,导致连接还没建立就失败了。

解决方法:

把网络操作放到子线程里,比如:

void Start()
{
    // 开子线程处理网络
    Thread netThread = new Thread(ConnectToServer);
    netThread.IsBackground = true;
    netThread.Start();
}

void ConnectToServer()
{
    try
    {
        IPAddress ipAddress = IPAddress.Parse("192.168.1.100"); // 替换成你的服务器IP
        IPEndPoint endPoint = new IPEndPoint(ipAddress, 7777);

        Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        socket.Connect(endPoint);

        byte[] send = Encoding.UTF8.GetBytes("Hello From Unity");
        socket.Send(send);

        byte[] recv = new byte[1024];
        int len = socket.Receive(recv);
        string recvData = Encoding.UTF8.GetString(recv, 0, len);

        // 注意:Unity的Debug.Log必须在主线程调用,用Invoke切回去
        InvokeOnMainThread(() => Debug.Log(recvData));

        socket.Close();
    }
    catch (Exception e)
    {
        InvokeOnMainThread(() => Debug.LogError("连接失败:" + e.Message));
    }
}

// 简单的主线程调度方法
void InvokeOnMainThread(Action action)
{
    if (action == null) return;
    lock (_mainThreadActions)
    {
        _mainThreadActions.Add(action);
    }
}

private readonly List<Action> _mainThreadActions = new List<Action>();
void Update()
{
    lock (_mainThreadActions)
    {
        foreach (var action in _mainThreadActions)
        {
            action.Invoke();
        }
        _mainThreadActions.Clear();
    }
}

这段代码里加了一个简单的主线程调度逻辑,确保Debug.Log这类Unity API在主线程执行,避免报错。


最后,测试步骤建议

  1. 先修改服务器代码,绑定0.0.0.0,启动服务器,看控制台输出的监听信息是否为0.0.0.0:7777
  2. 查电脑的内网IPv4,修改Unity客户端代码,直接用这个IP,并且把网络操作放到子线程。
  3. 给Windows防火墙添加7777端口的入站规则。
  4. 打包安卓APK,安装到手机,确保手机和电脑在同一Wi-Fi下,运行APK,看服务器控制台有没有收到连接请求。

如果还是不行,你可以在手机端的异常捕获里把错误信息打出来(比如连接超时、拒绝连接等),这样能更精准定位问题~

火山引擎 最新活动