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

Expo中Socket.io Android端无法连接,求localhost替代本地IP方案

Expo中Socket.io Android无法用localhost连接的解决方案

问题背景

在Expo项目中使用Socket.io时,iOS设备通过http://localhost:8001能正常连接后端服务,但Android设备(模拟器或真机)无法建立连接。将地址替换为本地网络IP(如http://192.168.1.91:8001)后连接恢复正常,但希望无需硬编码特定IP,直接使用localhost或127.0.0.1。

原因分析

  • iOS模拟器会自动将localhost映射到运行后端服务的宿主机(开发电脑),因此能正常连接。
  • Android模拟器中,localhost指向的是模拟器自身的本地回环地址,而非宿主机;真机使用localhost则指向设备自身,自然无法连接到电脑上的后端服务。

解决方案

1. 动态获取宿主机IP(适配模拟器+真机)

利用Expo内置的Constants模块获取当前设备连接的宿主机IP,无需硬编码:

import { useState, useEffect } from 'react'
import { io } from 'socket.io-client'
import Constants from 'expo-constants'
import { Platform } from 'react-native'

const getSocketUrl = () => {
  if (__DEV__) {
    if (Platform.OS === 'android') {
      // 从Expo配置中提取宿主机IP
      const hostUri = Constants.expoConfig?.hostUri;
      if (hostUri) {
        const [host] = hostUri.split(':');
        return `http://${host}:8001`;
      }
      // fallback到Android模拟器专属地址
      return 'http://10.0.2.2:8001';
    }
    // iOS端直接用localhost
    return 'http://localhost:8001';
  }
  // 生产环境替换为正式服务器地址
  return 'http://your-production-server:8001';
};

const socket = io(getSocketUrl())

const useSocket = () => {
  const [isConnected, setIsConnected] = useState(socket.connected)

  useEffect(() => {
    const onConnect = () => setIsConnected(true)
    const onDisconnect = () => setIsConnected(false)
    
    if (!socket.connected) {
      socket.connect()
    }
    
    socket.on('connect', onConnect)
    socket.on('disconnect', onDisconnect)

    return () => {
      socket.off('connect', onConnect)
      socket.off('disconnect', onDisconnect)
    }
  }, [])

  return { socket, isConnected }
}

export default useSocket

2. Android模拟器端口转发

通过adb命令将模拟器的端口转发到宿主机,这样就能直接用localhost连接:

adb reverse tcp:8001 tcp:8001
  • 每次重启模拟器后需要重新执行该命令,也可以在项目的package.json中添加脚本简化操作:
    "scripts": {
      "adb-reverse": "adb reverse tcp:8001 tcp:8001"
    }
    
    运行时只需执行npm run adb-reverse即可。

3. 使用Android模拟器专属地址10.0.2.2

Android模拟器提供了10.0.2.2这个特殊地址,专门用来映射到宿主机的127.0.0.1,可以通过平台判断来适配:

import { Platform } from 'react-native'
const URL = Platform.OS === 'android' ? 'http://10.0.2.2:8001' : 'http://localhost:8001'
const socket = io(URL)

注意:此方法仅适用于Android模拟器,真机测试仍需使用本地IP或动态获取IP的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:36:29