如何在React-Native中无需Internet即可通过Wifi发送和接收数据

时间:2019-06-03 09:39:04

标签: android react-native wifi-direct hotspot

我在React-Native上开发了一款游戏,该游戏可以完全脱机运行,而无需互联网连接,

该游戏将是多人1vs1游戏,并且玩家将通过Wifi热点(也称为wifi Direct)加入 该游戏还将允许用户彼此聊天

这一切都应该在没有互联网的情况下通过使用wifi来完成。

我尝试过“ React-Native-Wifi-Hotspot”,但是没有有关如何发送和接收数据的文档

我想通过2个已连接设备之间的wifi热点发送和接收对象/阵列。 P2P

我还阅读了有关react-native-wifi-p2p库的信息,但文档中说我们需要本地服务器,或者我真的不确定该怎么做。

3 个答案:

答案 0 :(得分:1)

所以,我会尽可能全面地保留这个答案。我将分享我构建的一个小型 react-native 应用程序,以帮助了解我们到底需要做什么。 此答案是 @ßãlãjî 答案的有效扩展。

我们需要的库:

// In App.js

import {createAppContainer} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import ClientScreen from './src/screens/ClientScreen';
import ServerScreen from './src/screens/ServerScreen';


const navigator = createStackNavigator({
  Server: ServerScreen,
  Client: ClientScreen
});



export default createAppContainer(navigator);

// In ClientScreen.js

import React, {useState, useEffect} from 'react';
import {View, Text, Button, FlatList, TextInput} from 'react-native';
import { NetworkInfo } from 'react-native-network-info';
var net = require('react-native-tcp');


const createClient = (ip, chats, setChats) => {
    const client = net.createConnection(6666,ip, () => {
        console.log('opened client on ' + JSON.stringify(client.address()));
        // client.write('Hello, server! Love, Client.');
      });
  
      client.on('data', (data) => {
        setChats([...chats, {id:chats.length+1, msg:data}]);
        // console.log('Client Received: ' + data);
  
        // client.destroy(); // kill client after server's response
        // this.server.close();
      });
  
      client.on('error', (error) => {
        console.log('client error ' + error);
      });
  
      client.on('close', () => {
        console.log('client close');
      });
      return client;
};


const ClientScreen = ({navigation}) => {

    const [client, setClient] = useState(null);
    const [chats, setChats] = useState([]);

    useEffect(async () => {
        let ip = await NetworkInfo.getIPV4Address(); //await NetworkInfo.getGatewayIPAddress();
        setClient(createClient(ip));

        return () => {};
    }, []);
    return <View>
        <Text>Client Screen</Text>
        <Button title="Stop Client" onPress={() => {
            if(client){
                client.destroy();
                setClient(null);
            }
        }}/>
        {client ? <Text>Client is on</Text>: null}
        <FlatList
            data={chats}
            renderItem={({item}) =>{
                return <Text style={{margin:10, fontSize:20}}>{item.msg}</Text>;
            }}
            keyExtractor={item => item.id}
        />
        <TextInput placeholder="Type a message" placeholderTextColor="black" style={{margin:10, borderWidth:2, color:'black'}} onSubmitEditing={({nativeEvent: {text}}) => {
            if(client){
                client.write(JSON.stringify({msg:text, id:1}));
            }
        }}/>
    </View>;
};



export default ClientScreen;
// In ServerScreen.js

import React, {useState} from 'react';
import {View, Text, Button, StyleSheet, FlatList} from 'react-native';
import { NetworkInfo } from 'react-native-network-info';
var net = require('react-native-tcp');


const createServer = (chats, setChats) => {
    const server = net.createServer((socket) => {
        console.log('server connected on ' + socket.address().address);
    
        socket.on('data', (data) => {
          let response = JSON.parse(data);
            setChats([...chats, {id:chats.length+1, msg:response.msg}]);
        //   console.log('Server Received: ' + data);
        //   socket.write('Echo server\r\n');
        });
    
        socket.on('error', (error) => {
          console.log('error ' + error);
        });
    
        socket.on('close', (error) => {
          console.log('server client closed ' + (error ? error : ''));
        });
      }).listen(6666, () => {
        console.log('opened server on ' + JSON.stringify(server.address()));
      });
    
      server.on('error', (error) => {
        console.log('error ' + error);
      });
    
      server.on('close', () => {
        console.log('server close');
      });
    
    return server;
};


const ServerScreen = ({navigation}) => {
    const [server, setServer] = useState(null);
    const [chats, setChats] = useState([]);
    const [ip, setIp] = useState('');
    
    return <View>
        {ip.length > 0? <Text>Server Screen: {ip}</Text>: <Text>Server Screen</Text>}
        <Button title="Start Server" onPress={async () => {
            if(!server)
              setServer(createServer(chats, setChats));
            try{
              let temp_ip = await NetworkInfo.getIPV4Address();
              setIp(temp_ip);
            }catch(e){
              console.log(e.message);
            }
        }}/>
        <Button title="Stop Server" onPress={() => {
            if(server){
                server.close();
                setServer(null);
            }
        }}/>
        <Button title="Go to Client Screen" onPress={() => navigation.navigate('Client')}/>
        {server ? <Text>Server is on</Text>: null}
        <FlatList
            data={chats}
            renderItem={({item}) =>{
                return <Text style={{margin:10, fontSize:20}}>{item.msg}</Text>;
            }}
            keyExtractor={item => item.id}
        />
    </View>;
};

const styles = StyleSheet.create({});

export default ServerScreen;

首先,如何运行这个应用程序。

  • 构建并安装到物理设备或模拟器中。
  • 首先,转到 ServerScreen。
  • 在 ServerScreen 中按下 Start Server 按钮。您将能够在屏幕上看到一个 IP 地址。
  • 现在导航到 ClientScreen。导航到此屏幕后,客户端套接字将自动调用。在这里您可以看到一个按钮和一个文本输入字段。在字段中输入一些消息并从键盘提交。按 Stop Client 按钮以避免任何错误。
  • 返回到 ServerScreen,您将能够看到您在 ClientScreen 中输入的消息。

现在,这是一个关于如何通过本地网络在 2 个设备之间进行通信的最小示例。但您可能会想,这个应用只能让我们在两个屏幕之间进行交流,对吗?

说实话,这是真的,到目前为止,我们只能使用此应用程序在 2 个屏幕之间进行通信,但是,我们用来使其工作的底层机制与我们在 2 个屏幕之间进行通信时所做的完全相同设备。

那么,如何针对不同的设备执行此操作。

假设我们有 2 个设备,即 A 和 B。我们想在这两个设备之间建立连接。首先,我们将打开 A 的 wifi 热点,并将 B 连接到该 wifi。

现在,在设备 A 上,我们将转到 ServerScreen 并启动服务器。在设备 B 上,转到 ClientScreen,您将看到“客户端已打开”信息出现,但是如果您在文本字段中输入一些消息并提交,您将不会在设备 A 上看到任何消息,这是因为要使其工作,我们需要对 ClientScreen.js 组件文件稍作改动。

更改自 =>

useEffect(async () => {
        let ip = await NetworkInfo.getIPV4Address(); //await NetworkInfo.getGatewayIPAddress();
        setClient(createClient(ip));

        return () => {};
    }, []);

到 =>

useEffect(async () => {
        let ip = await NetworkInfo.getGatewayIPAddress();
        setClient(createClient(ip));

        return () => {};
    }, []);

这样做的目的是,我们想要的 IP,将我们的设备 B 连接到设备 A,是设备 B 的网关的 IP(记住,我们将 B 连接到 A 的热点)。 就是这样。

现在只需重新构建并按照前面提到的步骤进行操作。输入消息并通过 B 上的 ClientScreen 提交后,您将能够在 A 的 ServerScreen 上看到它。

希望这对在设备之间建立本地套接字连接有困难的人有所帮助。 请注意,在 ServerScreen 和相同的代码库上,您可以确保在单个服务器上有多个客户端。

附注。我会确保经常查看此答案,以便您遇到任何问题,您都可以发表评论,我会尽快回复您。

答案 1 :(得分:0)

您可以使用名为React Native TCP的库,该库能够通过wifi发送和接收数据。

  

它是React Native中节点的net API。

它几乎与节点的net API相同,您可以使用net的文档。只是建议如何做,例如,您可以设置一个由两个按钮保持一致的连接页面。然后为一个定义热点创建功能,并为另一个定义热点连接功能。

答案 2 :(得分:0)

是的,您可以在两个设备之间共享数据,但是您提到了

React-Native-Wifi-Hotspot 

该库有助于建立两个设备之间的连接,但不共享任何内容(此lib只是用于建立连接而已)

那我如何共享数据?

1。您可以在 TCP UDP

的帮助下共享数据

使用 TCP 进行文件共享和数据通信的主要应用程序,例如shareit

UDP是什么?

我们可以使用UDP进行通信,但是传输的数据包数据可能会丢失(在tcp中不是,所以为什么使用)


现在您想像完全共享它的应用程序

它具有发送者和接收者相同的方式

发件人是tcp / udp中的客户端

接收者是tcp / udp中的服务器

现在我们看到详细的方法(服务器和客户端)

设备一是服务器(想像一下)

eg:

ip address 192.1.1.1

port: 6666

设备二是客户端

eg


ip address 192.2.2.2

port: 6666

通过端口的IP地址将数据发送到服务器

注意:设备2应该知道服务器的IP地址和端口号

现在我们将设备一配置为服务器

npm i react-native-tcp

了解ip

npm i react-native-network-info



import { NetworkInfo } from "react-native-network-info";
 
// Get Local IP
NetworkInfo.getIPAddress().then(ipAddress => {
  console.log(ipAddress);
});
 
// Get IPv4 IP (priority: WiFi first, cellular second)
NetworkInfo.getIPV4Address().then(ipv4Address => {
  console.log(ipv4Address);
});
 

仅在服务器设置中添加了端口(例如6666)

let server = net.createServer((socket) => {
      this.updateChatter('server connected on ' + JSON.stringify(socket.address()));

      socket.on('data', (data) => {
        this.updateChatter('Server Received: ' + data);
        socket.write('Echo server\r\n');
      });

      socket.on('error', (error) => {
        this.updateChatter('error ' + error);
      });

      socket.on('close', (error) => {
        this.updateChatter('server client closed ' + (error ? error : ''));
      });
    }).listen("6666", () => {
      this.updateChatter('opened server on ' + JSON.stringify(server.address()));
    });

    server.on('error', (error) => {
      this.updateChatter('error ' + error);
    });

    server.on('close', () => {
      this.updateChatter('server close');
    });

客户端设置(我添加了手动服务器IP地址(192.1.1.1)和端口(6666)):

 let client = net.createConnection(6666,192.1.1.1, () => {
      this.updateChatter('opened client on ' + JSON.stringify(client.address()));
      client.write('Hello, server! Love, Client.');
    });

    client.on('data', (data) => {
      this.updateChatter('Client Received: ' + data);

      this.client.destroy(); // kill client after server's response
      this.server.close();
    });

    client.on('error', (error) => {
      this.updateChatter('client error ' + error);
    });

    client.on('close', () => {
      this.updateChatter('client close');
    });

    this.server = server;
    this.client = client;
  }

  componentWillUnmount() {
    this.server = null;
    this.client = null;
  }

就这样

那我找你了

React-Native-Wifi-Hotspot 

此库仅有助于在设备之间共享IP地址,然后您建立tcp连接以在设备之间通信或共享文件

我希望它可以为您