How To Send & Receive Data Over Wifi Without Internet In React-Native
Asked Answered
R

3

9

I am developing a game on React-Native that works completely offline without needing internet connection,

The game will be multiplayer 1vs1 game, and players will join via Wifi Hotspot (also known as wifi Direct) The game will also allow users to chat with eachother

and this all should be done without internet by just using the wifi..

I have tried "React-Native-Wifi-Hotspot" but there is no documentation about how to send and receive data

I want to send and receive objects/arrays over wifi hotspot between 2 connected devices. P2P

I have also readed about react-native-wifi-p2p library but it's documentation says that we need a local server or something i am really not sure about how to do that.

Reservation answered 3/6, 2019 at 9:39 Comment(5)
Hi, were you able to work this out?Norford
nope, still looking just paused that project until I find a solution.Reservation
i added my brief answare belowEvadnee
I am also finding same case. did you got any solution?Tonguelashing
@RavinaVaishnav Check my answer. Hope it helps.Inhalator
I
13

So, I would keep this answer as comprehensive as possible. I will share a small react-native application I build to help understand what exactly we need to do. This answer is a working extension to @ßãlãjî 's answer.

Libraries we need:

// 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;

Firstly, how to run this application.

  • Build and Install this into a physical device or Emulator.
  • First, go to ServerScreen.
  • In the ServerScreen press on Start Server button. You will be able to see an IP address pop in the screen.
  • Now navigate to ClientScreen. The Client socket gets automatically invoked once you navigate to this Screen. Here you can see a button and a text input field. Type in some message in the field and submit from the keyboard. Press the Stop Client button to avoid any errors.
  • Go back to the ServerScreen you will be able to see the message that you typed in the ClientScreen.

Now, this is a minimal example of how to communicate between 2 devices through local network. But as you might be wondering, this app only lets us communicate between 2 screens right?

To be honest, thats true, we are only able to communicate between 2 screens so far using this application, but, the underlying mechanism we used to make it work is exactly same as what we would do in case of communication between 2 devices.

So, how to do it for different devices.

Lets say we have 2 device, namely A and B. We want to establish a connection between both of these device. Firstly, we will turn on the wifi hotspot of A, and will connect B to that wifi.

Now, on device A, we will go to the ServerScreen and start the server. On device B, go to ClientScreen and you will see "client is on" info appear, but if you type in some message in the textfield and submit, you wont be seeing any message appear on Device A, this is because to make it work, we need to change a little bit on the ClientScreen.js component file.

Change from =>

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

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

to =>

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

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

What this does is, the IP that we want, to connect our device B to device A, is the IP of the Gateway of device B (Remember, we connected B to the hotspot of A). That's it.

Now simply build again and follow the steps previously mentioned. Once you type in a message and submit it over the ClientScreen on B, you will be able to see it on ServerScreen of A.

Hope this helps anyone who is struggling with establishing a local socket connection between devices. Note that, you can sure have multiple clients with a single server with some little behaviourial change on ServerScreen and this same codebase.

PS. I will make sure that I keep a check on this answer frequently so that any issue you face, you can comment and I can get back to you ASAP.

Edit: If you want to sent messages to the client system from the main system (hotspot), then you can follow this answer https://mcmap.net/q/1172644/-how-to-send-data-from-device-that-hotspot-on-to-other-device-that-connected-with-hotspot-in-react-native.

Inhalator answered 4/4, 2021 at 18:4 Comment(3)
What do you mean by "turn on the wifi hotspot of A, and will connect B to that wifi" ... You mean with the android menus as if I wanted to share my 4G datas ? ... Can't we "create" a hotspot in React native ?Manthei
@Manthei Yes, from the android menu. You can use React to turn on the hotspot and do the necessary things, but this is a simple example and manually doing it suffices the use case here.Inhalator
Does an "hotspot" is "direct wifi" ? What's the difference ?Manthei
E
4

Yes You can share data between two devices but you mentioned

React-Native-Wifi-Hotspot 

this library is helps to establish connection between two devices but not share anything (this lib just made for establish connection thats it)

then how i share the data?

1.you can share data with help of TCP and UDP

The major applications using TCP/UDP for file sharing and data communicaiton like shareit


Now You imagine exactly share it app

it has sender and reciever same way

sender is a client in tcp/udp

reciever is a server in tcp/udp

Now we see detail approach(server and client)

device one is server(just Imagine)

eg:

ip address 192.1.1.1

port: 6666

device two is a client

eg


ip address 192.2.2.2

port: 6666

sending data to server by ip address with port

Note:device 2 should know server ip and port thats it

Now we configure device one as server

npm i react-native-tcp

to know 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);
});
 

server setup only i added port(eg 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');
    });

client setup(i added manualy server ip address(192.1.1.1) and port(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;
  }

thats it

then i come to your point

React-Native-Wifi-Hotspot 

this library just helps to share ip address between devices then you establish tcp connection to communicate or share files between devices

Note: file sharing possible with tcp ,udp , ftp , websocket,peer network and also over http

you can choose any one of above protocol to make file sharing application,extra tips ,you must learn about chunks and stream.(this helps you large file sharing) i hope it may help you

Evadnee answered 5/8, 2020 at 14:3 Comment(0)
S
0

You can use this library called React Native TCP which is able to send and receive data over wifi.

It is the node's net API in React Native.

It is almost identical to the node's net API and you can use net's documentation. And just a suggestion on how to do it would be that, You can set up a connection page consistent of two buttons for example. And then define a hotspot creating functionality for one and define a hotspot connecting functionality for another one.

Sphenoid answered 22/8, 2019 at 7:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.