Rapsssito / react-native-tcp-socket

React Native TCP socket API for Android, iOS & macOS with SSL/TLS support.
MIT License
315 stars 82 forks source link

iOS Network Interface Issue #14

Closed dalabarge closed 4 years ago

dalabarge commented 4 years ago

I'm using the following to create a connection a smart device that is hosting a TCP server on port 80. From the smart phone I connect to the broadcasted WiFi of the smart device, then initiate the following TCP connection. The same connection code works otherwise with Android.

TcpSocket.createConnection({
    host: '192.168.1.1',
    port: 80,
    localAddress: ...,
})

Per several hours of debugging and internet search I find that localAddress is required so that is why it is included otherwise I'd omit it. The problem is that when localAddress is "0.0.0.0", not specified, is "192.168.1.1", or anything other than "ap1" (current data port) then the error is:

Unknown interface. Specify valid interface by name (e.g. "en1") or IP address.

When localAddress is "127.0.0.1" or instead I supply interface as "192.168.1.1" or "ap1" then the error is:

Error in connect() function

Could this be related to: https://github.com/aprock/react-native-tcp/pull/7

With many IoT and smart devices the goal during setup is that the device and the phone talk directly to each other over the smart device's WiFi access point and that the phone's cellular interface is NOT used to resolve the smart device's IP address. Any idea how to get this working cross platform?

Dependency Version
iOS latest on iPhone X device
react-native 0.61.5
react-native-tcp-socket 3.0.5
Rapsssito commented 4 years ago

@dalabarge, thanks for your feedback! However, this looks like two issues:

Could you create two different issues indicating all the relevant data for each problem, please?

dalabarge commented 4 years ago

Let's ignore the timeout issue for now as that's not near as critical as just getting things connecting. All relevant iOS information is available in this issue.

Rapsssito commented 4 years ago

My understanding is that in iOS you need to specify a localAddress to connect to 192.168.1.1. However, when you set your localAddress as those examples you provided, you get an error. Is that correct?

dalabarge commented 4 years ago

Yes that is precisely the problem. If I use localAddress set to 127.0.0.1 it seems to accept it but then it errors out in the connect().

Rapsssito commented 4 years ago

Yes that is precisely the problem. If I use localAddress set to 127.0.0.1 it seems to accept it but then it errors out in the connect().

You cannot set localAddress to 127.0.0.1 because that is the device loopback address. You must set your localAddress to your device IP address, otherwise it will throw an error.

Rapsssito commented 4 years ago

If you are connecting to a non-internet-accessible WiFi network, you must specify a localAddress, which must be your device's IP address in that network, so the SO knows where to bind the socket.

dalabarge commented 4 years ago

So you're saying that the localAddress needs to be the IP of my phone as assigned by the WiFi AP of the smart device? Makes sense I suppose, though I'm surprised the OS level libs cannot resolve that automatically.

Using react-native-network-info package I was able to call NetworkInfo.getIPAddress().then((localAddress) => { TcpSocket.createConnection(...) }) to get the resolved 192.168.1.2 IP address for the smart phone on the IoT device's WiFi AP.

dalabarge commented 4 years ago

It would also appear that by fixing this localAddress issue the previously mentioned timeout event handling no longer errors when called on iOS. Thank you for your help and clarification on localAddress usage.

Rapsssito commented 4 years ago

@dalabarge glad it worked! I would recommend you to use react-native-netinfo, since it is actively developed by the react native community. A few days ago my PR to fetch info from a specific interface was merged, providing reliable an stable tools for getting the network info from the interface, even if it is not connected to the internet.

dalabarge commented 4 years ago

Yes I ended up using that package per your suggestion and this worked well enough.

NetInfo.fetch('wifi').then((info) => {
  TcpSocket.createConnection({
    host: '192.168.1.1',
    port: 80,
    localAddress: info.details.ipAddress,
  })
})
caike commented 4 years ago

@dalabarge Thank you for this! For future reference, one small tweak.. I believe it's info.details.ipAddress

dalabarge commented 4 years ago

@caike you are most correct, I was using ipAddress instead. I've updated my original post to avoid copy paste error confusion.