In my setup I have 2 apps. One running on my local emulator on my macbook. The other on my physical android phone.
In these apps I use ZeroMQ to have a Req/Rep socket, which under the hood uses TCP.
When hosting my server on the emulated device using port 6543, with it's IP at wlan0 I cannot connect to it from my phone. Reversing the roles works fine where the phone hosts the server and emulator connects to it, but in the long run I need emulators to run this server. Eventually iOS developers want to talk to an Android server, so I'd prefer to keep them using emulators for this.
My understanding is that android emulators exist behind a virtual router, so if you want to talk to them you have to use port forwarding.
I've done this for my emulator. Using redir add tcp:7654:6543
. If I understand this correctly then port 7654 of my Macbook should have its traffic redirected to port 6543 of my emulator.
Rather than connect directly to the IP of wlan0
on my emulator, I believe I should be using the IP of my Macbook. For this I run ifconfig | grep "inet "
and connect to the IP address that comes back here.
Trying to receive packets in my app though I still don't see traffic.
Additionally I installed Wireshark and filter on tcp.port == 7654
on the wifi interface of my Macbook. While I do see some messages I'm not sure if what I'm seeing is my message itself, or just the TCP handshake as I see multiple SYN
and [RST, ACK]
but not clear if I should actually be able to see the payloads I'm sending?
I'm not sure at this point what to do. How can I actually verify the traffic is getting to my macbook ok? and how can I verify the forwarding is setup correctly?
So it turns out there are quite a few steps to solve this.
First we have to do the port forwarding as mentioned in the official android docs so we can get messages to the emulator:
in a terminal run adb devices
to get the port of the device
List of devices attached
emulator-5554 device
You'll then need to run telnet localhost 5554
using the port that the device is on.
From here you'll be prompted for an auth key:
* Android Console: Authentication required
* Android Console: type 'auth <auth_token>' to authenticate
* Android Console: you can find your <auth_token> in
* '/Users/<your_username>/.emulator_console_auth_token'
Do as the prompt says, open a second terminal and look at the file to get your token.
Back in the first terminal you'll need to execute
auth <your_token>
Then you can setup your port forward
redir add tcp:8765:7654
This redirects from the loopback port of your Macbook "8765" to the android emulator port "7654".
Now you have to redirect from your Macbook public IP to its internal loopback address.
First go to System Preference -> Sharing -> enable Remote Login
so that we can setup a port forward using SSH.
While the SSH requires authentication, and with turning on I'm guessing there may be some security concerns as you're opening up your laptop to external traffic. This may be somewhere to research more before you proceed.
If this is ok you can then run ssh -v -g -L 9876:localhost:8765 localhost
which will then run in the terminal and perform the forwarding for you.
The final result is:
macbook_ip:9876
forwards to macbook_loopback_ip:8765
forwards to android_emulator:7654
On the Emulator side you have to bind to one of its addresses automatically assigned by the OS:
10.0.2.15:7654
And on the physical device side you connect to the Macbook IP:port. This number you'll need to look up yourself by running ifconfig | grep "inet "
As an example you may connect to something like this:
10.0.0.253:9876
At this point you should have your physical Android phone able to send messages to, and receive from the socket you bound in your Emulator.