Server(AndroidWebServer) not reachable from pc - android

I have created AndroidWebServer on my android phone.
When I try to access 192.168.1.150:8000 (phone address) I have good response from the server. But when I try to access the same url from the pc (connected via WiFi on the same network) nothing happens.
When the server is active if I run this
adb shell netstat -at
tcp 0 0 ::ffff:127.0.0.1:8000 :::* LISTEN
That is weird because other services got foreign address
tcp 0 0 ::ffff:192.168.1.150:54 ::ffff:173.194.76.188:5 ESTABLISHED
tcp 0 0 ::ffff:192.168.1.150:36 ::ffff:31.13.92.33:http ESTABLISHED
for my service the foring address is :::*
I am not sure what I do wrong
https://github.com/lopspower/AndroidWebServer
AndroidWebServer androidWebServer = new AndroidWebServer(8000);
androidWebServer.start();
What should I change in order my phone to be accessible from my pc connected to the same WiFi network?
Thanks

Looks like your server is listening on localhost. That means it will only accept connections that originate on the local machine. Try listening on 0.0.0.0 instead; that means you accept connections from all origins.
EDIT
Change this line:
AndroidWebServer androidWebServer = new AndroidWebServer("0.0.0.0", 8000);

Related

Can't ping Gateway if Access Point has no internet connection

In my app I programmatically connect to an Access Point that has no access to the internet via WifiManager and WifiConfiguration. Later on I have to access a device connected to it to read data – but I didn't get that far.
After connecting to the Wifi I'm getting my DHCP setup just fine, but if I try to ping the Gateway address by typing:
$ adb shell
OnePlus6:/ $ ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
^C
--- 192.168.1.1 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1015ms
The gateway is unreacheable...
I suspect this has to do with the fact that Android (9?) re-routes all traffic in case of a "dead" Wifi over to mobile data – for example you can still browse the internet just fine.
You can easily replicate the issue like this:
Connect to an Access Point w/o internet access
Check if your internet still works (e.g. go to google.com)
Connect you phone via adb and ping the address of your AP
Any ideas on how to force the traffic trough Wifi, even if it's "offline"?
Edit: Output of ip route show:
OnePlus6:/ $ ip route show
10.16.52.64/29 dev rmnet_data0 proto kernel scope link src 10.16.52.67
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.116
Ok, I've found a solution. One has to bind the current process to the correct network, which can be done like this:
connectionManager = (ConnectivityManager)
context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
connectionManager.registerNetworkCallback(request.build(), new ConnectivityManager.NetworkCallback() {
public void onAvailable(Network network) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connectionManager.bindProcessToNetwork(network);
} else {
ConnectivityManager.setProcessDefaultNetwork(network);
}
}
});

Why am I sending an RST if my socket is connected and not closed?

I have an Android device that communicates wirelessly with a PC, using a java.net.Socket. Everything hums along fine, but if I do nothing (i.e., no network use) for exactly 1 minute then when the Android sends a packet of data to the PC the PC receives it and sends an ACK, but the Android responds with an RST.
From Wireshark ( 10.1.2.1 is the Android, 10.1.2.11 is the PC)...
356 0.112470 10.1.2.1 10.1.2.11 TCP 97 34360→181 [PSH, ACK] Seq=1
Ack=1 Win=4935 Len=31 TSval=156103571 TSecr=320673352
359 0.000011 10.1.2.11 10.1.2.1 TCP 66 181→34360 [ACK] Seq=1 Ack=32
Win=260 Len=0 TSval=320738236 TSecr=156103571
360 0.000304 10.1.2.1 10.1.2.11 TCP 60 34360→181 [RST] Seq=32 Win=0
Len=0
At this point if I interrogate the socket's member variables it says . . .
isConnected = true
isCreated = true
isInputShutdown = false
isOutputShutdown = false
isClosed = false
isBound = true
... which looks like I should still be receiving packets just fine. So how do I figure out why I'm sending RST?
N.B. - there are no settings to "sleep" or turn off the wifi or display or any other battery-saving features set enabled on this device.
The 1 minute delay looks like a timeout. It may be the SO_TIMEOUT but this does not generate network activity on itself. Also the fact that the last packet sent contains 31 bytes of data seems to indicate that the application is involved. A possible scenario would be :
The android application times out (on its own or triggered by a socket's SO_TIMEOUT)
It sends a last chunk of data, e.g. by flushing an output stream.
It closes abruptly the socket, for example by using the setSoLinger(true, 0) socket option.
None of those Socket methods returns the state of the connection. They are all about the internal state of the java.net.Socket object, as determined by which constructors and methods you have called on it. They don't magically start returning false if the peer drops the connection.
You will find when you go to use the socket for I/O that you will get an IOException: 'connection reset'.
Why the connection has been reset is another matter. The usual reason is that you had sent to a connection that had already been closed by the peer, or that the peer closed the connection without reading all the data that had already arrived. In other words, an application protocol error. There are other reasons, but these are the most common.
This could be caused by your NAT router that tries to close sockets after a timeout to free up resources. Turning on keep_alive may help. You can also try to create your own network with static IP addresses bypassing the router to rule out this hypothesis.
When the connection is closed the isClosed() method should return TRUE.
It's OK for the isConnected() method to return TRUE even if the connection has been closed because what that method tells you is "if ever you managed to get connected", the variable state is not changed/refreshed when you get disconnected.
However in your case the connection has definitely not been closed as per documentation.
For more info see:
https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#isConnected--
https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#isClosed--
Note: It might help you to set to TRUE setKeepAlive(boolean)
See also:
https://docs.oracle.com/javase/8/docs/api/java/net/SocketOptions.html#SO_KEEPALIVE
https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#setKeepAlive-boolean-
Back to the problem, check for one of the following:
Can you make sure for some reason there isn't another device with
the same IP as the Android? Also turn off you 3G/4G and stay
connected only in the wireless network.
Is there a router doing NAT ? In this case the router can send the
RESET flag.
If everything seems fine (it's your Android phone replying with RST) and the SO_KEEPALIVE does not work then it might be some application level error that is killing the connection.

Can't listen TCP on local address with Android and NetworkComms.Net

I'm trying to listen on TCP on my phone. I'm working with Android.Xamarin and NetworkComms.Net.
To listen, I use this on the server and it works:
Connection.StartListening(ConnectionType.TCP, new IPEndPoint(IPAdresse.Any, 7878));
But on the phone, it doesn't. It open only on IPv6 address:
Server listening for UDP connection on: ::1:7878
2607:fa48:6d6a:b421:11e5:620b:6b3:279e:7878
2607:fa48:6d6a:b421:62f1:89ff:fe1b:d52c:7878
When I try to put my own IP instead of IPAdresse.Any (smth like 192.168.0.172), NetworkComms tells me it cannot open a port on this EndPoint. I tried every port with a for and no one can be used...
I have Internet and Access Internet State permissions in the manifest.

Why does my service always bind to ipv6 localhost instead of ipv4?

I have a service that creates a ServerSocket and binds to localhost:7060. When I did "netstat -an" on my android device, I see it is using ipV6 localhost instead of ipv4 localhost interface.
The output is like this:
tcp6 0 0 ::ffff:127.0.0.1:7060 :::* LISTEN
The ports that use ipV4 are listed like this:
tcp 0 0 127.0.0.1:5060 0.0.0.0:* LISTEN
What is the trick to force it to use IPv4 always?
I am setting up a port forward rule using iptables. The version I have supports ipv4 destination addresses.
This is how I am creating my Java code for listening on the port.
InetAddress localAddress = Inet4Address.getByName("localhost");
//InetAddress localAddress = Inet4Address.getLocalHost();
sockServer = new ServerSocket(nPort, 20, localAddress);
I followed other advice like setting system property to prefer ipV4 in the startup of my service. That didn't make any difference.
System.setProperty("java.net.preferIPv4Stack", "true");
I am running this on Android 2.3 built for an embedded device.
Update:
I checked InetAddress.java sources in android tree. It is reading the above flag with a line like below.
static boolean preferIPv6Addresses() {
String propertyName = "java.net.preferIPv6Addresses";
String propertyValue = AccessController.doPrivileged(new PriviAction<String>(propertyName));
return Boolean.parseBoolean(propertyValue);
}
Now I am not sure System.setProperty() call is really changing the value read by above code.
In theory a IPv6 server listens to IPv4 as well, since IPv4 address space is a subset of IPv6, is this causing real problems to you?
A trick that might work is to use "127.0.0.1" instead of "localhost", which has IPv4 and IPv6 addresses associated.

Can't use ServerSocket on Android

I'm trying to listen on a port using ServerSocket on an Android device. I want to be able to connect to this port over WiFi using a computer on the same network.
I get no exception when binding it to a port, however when I check netstat it says:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 (null):4040 (null):* LISTEN
I've tried countless ways of binding it to localhost, 0.0.0.0, the WiFi LAN IP address of the device with SocketInetAddress and InetAddress.getByName. Nothing seems to work.
When I try to connect to the port from a computer in the same WiFi (I've tried both netcat and Java's Socket.connect()), all I can see in Wireshark is an ARP request:
Who has [phone's LAN address]? Tell [computer LAN address].
This request repeat itself until timed out.
I've tried the reverse way, by setting the ServerSocket on the computer and connecting to that port from the phone, that works very well.
My testing phone is an Samsung Spica i5700 with a custom ROM.
Any ideas?
Edit:
The code is simple as this:
ServerSocket server = new ServerSocket();
server.setReuseAddr(true);
server.setTimeout(0);
server.bind(new InetSocketAddress(4040));
Socket client = null;
while((client = server.accept()) == null);
// Connected
enter code here
enter code here
Instead of using server.bind, try initializing the server socket like this:
server = new ServerSocket(4040);
Also, server.accept() will actually block until a connection is made, so you don't need that while loop (see: http://download.oracle.com/javase/1.5.0/docs/api/java/net/ServerSocket.html#accept() )
I struggled with this too and was only able to connect to my Android server by using:
ServerSocket myServerSocket = new ServerSocket();
String hostname = getLocalIpAddress();
myServerSocket.bind(new InetSocketAddress(hostname, myPort));
Where hostname was the local IP, which I got using the getLocalIpAddress() function from this page:
https://github.com/Teaonly/android-eye/blob/master/src/teaonly/droideye/MainActivity.java
I was able to get this working by using
ServerSocket server = new ServerSocket( myTcpPort, 0, addr );
where addr = InetAddress of your phone. Otherwise, it only seems to bind to localhost (127.0.0.1). Also, I'm using port 8080.

Categories

Resources