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

React Native热点设备通信问题:设备A无法向设备B发送消息

问题:WiFi热点下React Native消息应用无法从服务器(设备A)向客户端(设备B)发送消息

设备A开启热点并运行TCP服务器,设备B连接热点后可正常向A发送消息,但A无法向B推送消息。排查发现设备A网关IP为0.0.0.0,现有TCP实现存在未保存客户端连接实例、状态更新闭包陷阱、缺少主动发送逻辑三个核心问题。


修复方案

1. 服务器端改造:保存客户端Socket并修复状态更新

修改createServer函数,存储客户端连接的Socket实例,同时使用函数式状态更新避免闭包导致的状态过时问题:

// ServerScreen 修改后的 createServer 函数
import React, {useState} from 'react';
import {View, Text, Button, StyleSheet, FlatList, TextInput} from 'react-native';
import { NetworkInfo } from 'react-native-network-info';
var net = require('net');

const createServer = (setChats) => {
  let clientSocket = null; // 持久化客户端连接的socket
  const server = net.createServer((socket) => {
    console.log('客户端已连接:' + socket.address().address);
    clientSocket = socket; // 保存当前客户端socket

    socket.on('data', (data) => {
      let response = JSON.parse(data);
      // 使用函数式更新获取最新聊天记录状态
      setChats(prevChats => [...prevChats, {id: prevChats.length + 1, msg: `Client: ${response.msg}`}]);
    });

    socket.on('error', (error) => {
      console.log('连接错误:' + error);
      clientSocket = null; // 出错时清空无效连接
    });

    socket.on('close', (error) => {
      console.log('客户端断开连接:' + (error ? error : ''));
      clientSocket = null; // 连接关闭时清空socket
    });
  }).listen(6666, '0.0.0.0', () => { // 显式绑定0.0.0.0,监听所有网卡
    console.log('服务器启动:' + JSON.stringify(server.address()));
  });

  // 新增服务器主动发消息的方法
  server.sendMessage = (message) => {
    if (clientSocket && clientSocket.writable) {
      clientSocket.write(JSON.stringify({msg: message}));
    }
  };

  server.on('error', (error) => {
    console.log('服务器错误:' + error);
  });

  server.on('close', () => {
    console.log('服务器已关闭');
    clientSocket = null;
  });

  return server;
};

2. 更新ServerScreen组件:添加消息输入与发送UI

给服务器端添加输入框,用于手动触发向客户端发送消息,同时修正状态传递逻辑:

// 修改后的 ServerScreen 组件
const ServerScreen = ({navigation}) => {
    const [server, setServer] = useState(null);
    const [chats, setChats] = useState([]);
    const [ip, setIp] = useState('');
    const [serverMsg, setServerMsg] = useState(''); // 服务器输入的消息内容

    return <View style={{padding: 15}}>
        {ip.length > 0 ? 
          <Text style={{fontSize:16, marginVertical:10}}>服务器IP:{ip}</Text> : 
          <Text style={{fontSize:16}}>服务器页面</Text>
        }
        <Button title="启动服务器" onPress={async () => {
            if(!server)
              setServer(createServer(setChats)); // 仅传递setChats,避免状态过时
            try{
              let temp_ip = await NetworkInfo.getIPV4Address();
              setIp(temp_ip);
            }catch(e){
              console.log(e.message);
            }
        }}/>
        <Button title="关闭服务器" onPress={() => {
            if(server){
                server.close();
                setServer(null);
            }
        }}/>
        <Button title="切换到客户端页面" onPress={() => navigation.navigate('Client')}/>
        {server ? <Text style={{marginVertical:10}}>服务器已启动</Text>: null}
        
        {/* 新增服务器消息输入框 */}
        <TextInput 
            placeholder="输入消息发送给客户端" 
            placeholderTextColor="#666" 
            style={{marginVertical:15, borderWidth:1, borderColor:'#ccc', padding:10, borderRadius:4, color:'#333'}} 
            value={serverMsg}
            onChangeText={text => setServerMsg(text)}
            onSubmitEditing={() => {
                if(server && serverMsg.trim()){
                    server.sendMessage(serverMsg);
                    // 服务器本地显示发送的消息
                    setChats(prev => [...prev, {id: prev.length+1, msg: `Server: ${serverMsg}`}]);
                    setServerMsg('');
                }
            }}
        />

        <FlatList
            data={chats}
            renderItem={({item}) =>{
                return <Text style={{margin:10, fontSize:18}}>{item.msg}</Text>;
            }}
            keyExtractor={item => item.id.toString()} // 确保key为字符串类型
        />
    </View>;
};

const styles = StyleSheet.create({});

export default ServerScreen;

3. 客户端修正:统一消息解析格式

客户端收到服务器消息时,按JSON格式解析,保持和发送逻辑一致:

// ClientScreen 修改后的 createClient 函数
const createClient = (ip, setChats) => {
    const client = net.createConnection(6666,ip, () => {
        console.log('客户端已连接:' + JSON.stringify(client.address()));
      });
  
      client.on('data', (data) => {
        try {
          let response = JSON.parse(data);
          // 使用函数式更新获取最新聊天记录
          setChats(prevChats => [...prevChats, {id: prevChats.length+1, msg: `Server: ${response.msg}`}]);
        } catch (e) {
          console.log('解析服务器消息失败:', e);
          // 兼容非JSON格式消息
          setChats(prevChats => [...prevChats, {id: prevChats.length+1, msg: data.toString()}]);
        }
      });
  
      client.on('error', (error) => {
        console.log('客户端错误:' + error);
      });
  
      client.on('close', () => {
        console.log('客户端已断开');
      });
      return client;
};

关键修复点说明

  • 必须保存客户端Socket实例,才能让服务器主动发起消息推送
  • 使用React函数式状态更新(setChats(prev => ...)),避免闭包导致的旧状态引用问题
  • 服务器显式绑定0.0.0.0,确保能接收热点子网内的所有连接请求
  • 客户端与服务器统一使用JSON格式传递消息,避免解析错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 13:33:04