Cannot get http server work on android - android

I have a http server code (I tried both TJWS or NanoHTTPD), the client from the same application would connect to server running on port 8080 or whatever.
I am starting server object in a separate AsyncTask so it should be okay.
While NanoHTTPD completely failed to start other ways I can see from TJWS logs, it says something like;
server listening on 0.0.0.0/0.0.0.0 port:0 localport:8080
This means server started successfully, first question is 0.0.0.0 bind address acceptable? I mean it should be 127.0.0.1 instead? sorry if that is a noob question.
When I connect to my emulator using adb shell and run netstat, I can see the following lines
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:5037 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN
tcp 0 0 10.0.2.15:5555 10.0.2.2:52132 ESTABLISHED
tcp6 0 0 :::8080 :::* LISTEN
By googling I learned that 0 :::8080 means server is listening on ipv6 and ipv4 both and that is okay.
But from my client code when i tried to access it continues to wait for eternity.
my httpClient Code
try {
URL url = new URL("http://0.0.0.0:"+8080+"/media");
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
while((line = br.readLine()) != null){
Log.d("server", line);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

For the server, the address 0.0.0.0 is like a wildcard and means, it is listening on all IP addresses the device has.
For the client, you need to use a real IP address like 127.0.0.1

After debugging a little I found that problem is not where client opens a connection but issue was at where server was starting it never returned onPostExecute() method, but after wrapping my server start code inside a Runnable
new Thread(new Runnable() {
#Override
public void run() {
Log.d("server", "server starting on port: " + port);
srv.serve();
}
}).start();
it Works!!
Server is a infinite loop so does it have to be started from inside thread? I thought AsyncTask can handle that?
Its also worth mentioning that client side connection must also be wrapped inside AsyncTask

Related

Problems writing to network device using sockets

I have a wireless device communicating over port 22 connected to my network. Once the device starts up, it immediately starts sending log data. Once this device is sent a command, it stops logging and responds accordingly. This all works, I have tested it using a telnet client.
My problem is that I can't seem to send it a command properly in my app. I am reading the log data as planned, but when I send it a command, in this case the command "r", it continues outputting log data instead what it should be showing me for that particular command. This has to mean that I am not properly sending the command. This is my code for the task that sends it the command and logs the output in the android logcat:
public class ReceiveVarTask extends AsyncTask<Void, Void, Void>{
String dstAddress;
int Port;
ReceiveVarTask(String addr, int port) {
dstAddress = addr;
Port = port;
}
protected Void doInBackground(Void... vars){
Socket socket = null;
String command = "r";
try {
Log.i(TAG, "Connecting to port 22");
socket = new Socket(dstAddress, Port);
Log.i(TAG, "Connected to port 22");
PrintWriter writer = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
writer.println(command);
String line = reader.readLine();
Log.i(TAG, line);
while(line!=null && !isCancelled()){
line = reader.readLine();
Log.i(TAG, line);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
protected void onPostExecute(Void arg) {
taskRunning = false;
}
}
What am I doing wrong? Why is it not registering the command?
UPDATE:
I have used several telnet clients for testing, and the server is reading the 'r' command as expected on some. It works using a windows telnet client, and it works using the vSSH app by Velestar. Interestingly enough, when testing this with the android telnet client by ClockworkMod, the server is not registering the command either.
Could it be something to do with encoding?
Do I need any additional permissions to work with sockets? I have android.permission.INTERNET declared in the manifest.
UPDATE 2:
The developer of of the hardware just told me that the hardware is expecting the command to be ASCII encoded and CR terminated. So I will try changing PrintWrite initialization to:
PrintWriter writer = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream(), "ASCII")), true);
and the print command to:
writer.print(command+"\r");
Changing the the encoding type to "US-ASCII" and adding a carriage return instead of a new line did the trick. I'm able to read and write data as expected.
From my understanding of your problem description, you have a telnet server, and when a telnet client connects to that server, the server start sending the client log data. The client may send an "r" to the server to stop the log stream.
I suggest you first confirm using another telnet client that sending an "r" does stop the server from generating more log data.
You could use Wireshark to check if the "r" command is indeed sent.

Socket not flushing data

I did a script to exchange data between a client and a server with socket on specific port.
In order, I am expecting:
Server is listening
Client opens a socket
Server akwnoledges by sending a int -> never received !
I just noticed that my client receives the int, when I quit the server brutally
Here is my (simple) code.
Client:
Socket socket = new Socket(SERVER_ADDR, PORT);
DataOutputStream dOut = new DataOutputStream(socket.getOutputStream());
DataInputStream dIn = new DataInputStream(socket.getInputStream());
Log.v("[DEBUG]", "waiting aknowledgement");
status = dIn.readInt(); //<-- BLOCKS HERE
Log.v("[DEBUG]", "ack"); //<-- RECEIVED WHEN SERVER IS EXITED
Server:
try {
DataInputStream stdIn = new DataInputStream(client.getInputStream());
DataOutputStream stdOut = new DataOutputStream(client.getOutputStream());
while (incoming) {
stdOut.writeInt(1);
stdOut.flush();
System.out.println("Waiting...");
var_from_client = stdIn.readInt(); //<-- BLOCKS HERE (BECAUSE CLIENT IS BLOCKED)
// ...
}
} catch (Exception e) {}
How to explain this error?
'Socket not flushing data' has exactly nothing to do with it. This is a deadlock, caused by a bug in your application.
Your server sends an int.
Your client receives the int.
Your server blocks trying to read another int.
Your client doesn't send an int.
The server can never send another int because it is blocked waiting for the non-existent reply int.
Your client blocks while trying to receive another int because the server is blocked from sending it.
Solution: send the int from the client.
Notes:
Flushing the output stream of a socket does nothing, and neither does flushing a DataOutputStream wrapped directly around it.
NEVER ignore exceptions.

Android tcp connection from client

I'm trying to make my android phone a client to a server I wrote in python. The server works good (I have tried it) but I can't seem to connect the phone with the server.
This is the function that should create the connection:
public String createConnection() throws IOException{
InetAddress serverAddr = InetAddress.getByName(ipString);
clientSocket = new Socket(serverAddr, portNumber);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.writeBytes(Client.INIT_HEY.name());
String ans = inFromServer.readLine();
return ans;
}
ipString is the server ip received by the user, portNumber is the port number and they are both correct.
When I try to connect to the server, I receive "null" as the error message.
Any thoughts?
Thanks!
Try it over wifi.
If you can find the phone's IP address, try ping it from your dev system.
If your are on cell network, try access web site from browser, make sure the network connection is working.
The error was because I was running a tcp connection on the main thread.. I could've fixed it by making the class an AsyncTask but I prefered adding this:
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Thanks all!

Data transfer between two Wifi devices

I have searched in Google. In Android 2.2 and sdk 8 how can I use SSID in a List in Android ?
By using SSID should get specific wifi enabled device properties by programmatically. With that help, should transfer the data between two Wifi enabled devices in Android.
To send data in a meaningful manner between two Android devices you would use a TCP connection. To do that you need the ip address and the port on which the other device is listening.
Examples are taken from here.
For the server side (listening side) you need a server socket:
try {
Boolean end = false;
ServerSocket ss = new ServerSocket(12345);
while(!end){
//Server is waiting for client here, if needed
Socket s = ss.accept();
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter output = new PrintWriter(s.getOutputStream(),true); //Autoflush
String st = input.readLine();
Log.d("Tcp Example", "From client: "+st);
output.println("Good bye and thanks for all the fish :)");
s.close();
if ( STOPPING conditions){ end = true; }
}
ss.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
For the client side you need a socket that connects to the server socket. Please replace "localhost" with the remote Android devices ip-address or hostname:
try {
Socket s = new Socket("localhost",12345);
//outgoing stream redirect to socket
OutputStream out = s.getOutputStream();
PrintWriter output = new PrintWriter(out);
output.println("Hello Android!");
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
//read line(s)
String st = input.readLine();
//. . .
//Close connection
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
For data Transfer between 2 devices over the wifi can be done by using "TCP" protocol. Connection between Client and Server requires 3 things
Using NSD Manager, Client device should get server/host IP Address.
Send data to server using Socket.
Client should send its IP Address to server/host for bi-directional communication.
For faster transmission of data over wifi can be done by using "WifiDirect"
which is a "p2p" connection. so that this will transfer the data from one to other device without an Intermediate(Socket). For example, see this link in google developers wifip2p and P2P Connection with Wi-Fi.
Catch a sample in Github WifiDirectFileTransfer

Android, problems with SocketAddress and sockets. Reverse lookup?

i have a problem with Android. I am trying to connect to a server with a proxy with no luck.
I have this code that works fine on normal Java. It only defines a proxy server and creates a socket that would connect to google with that proxy. It sends a simple GET request and then shows the response.
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import java.net.SocketAddress;
public class Main {
public static void main(String[] args) {
try{
//create the proxy info
SocketAddress socketAddress = new InetSocketAddress("78.137.18.67" , 8364);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, socketAddress);
// create the socket with the proxy
Socket socket = new Socket(proxy);
// connect to some address and send/receive data
socket.connect(new InetSocketAddress("www.google.com", 80));
socket.getOutputStream().write("GET /index.html HTTP/1.1\r\nHost: www.google.com\r\n\r\n".getBytes("UTF-8"));
byte result[] = new byte[1024];
socket.getInputStream().read(result);
socket.close();
System.out.println(new String(result));
}catch(Exception e){
e.printStackTrace();
}
}
}
The problem with android, with a code similar like that, is that the InetSocketAddress is doing something strange. It seems that it does a reverse lookup of the given ip, and then the socket created with the proxy tries to connect with the resolved host name, in this case is 78-137-18-67.dynamic-pool.mclaut.net.
This would not be a problem (except on performance) if the socket could resolve the hostname back to the ip address. The fact is that this hostname cannot be resolved to ip address with my internet connection (i don't know if others can do). So the reverse lookup is working fine but the normal lookups fails, so when the socket tries to connect through the proxy it raises the following exception:
08-25 19:26:46.332: ERROR/Microlog(3526): 40274 SocketConnection
[ERROR] Error establishing connection java.net.SocketException: SOCKS
connection failed: java.net.UnknownHostException:
78-137-18-67.dynamic-pool.mclaut.net
So the question is, why it is trying to connect with the hostname if i gave the ip address? Is there any way to avoid this lookup? I have tried with createUnresolved of InetSocketAddress but in this case the socket hangs on connection.
Is not a waste of time, internet connection, etc, to do a reverse DNS lookup to get the hostname (if any), and later when the socket needs to connect, resolve again the host to an ip address?
NOTE: this code is an example, the real app do not perform any http request in this way. It uses binary data packets.
To prevent a reverse lookup, you can create the InetAddress with getByAddress(byte[]).
Then pass the InetAddress instance into the InetSocketAddress constructor.
Alternatively, use the factory method InetSocketAddress.createUnresolved(String,int)
Yes it seems that the particular constructor of InetSocketAddress does a reverse DNS lookup: http://mailinglists.945824.n3.nabble.com/Android-and-reverse-DNS-lookup-issues-td3011461.html
Also, it seems that this does not happen anymore on Android 2.3.4.
In android you have to do everything with background process so that you do not write code for socket in onCreate method directly you have to do this in background so that your ui does not hangs
something like this
new Thread(new Runnable() {
#Override
public void run() {
try {
client = new Socket(ipaddress, port);
printwriter = new PrintWriter(client.getOutputStream(), true);
InputStream is = client.getInputStream();
printwriter.write(msg);
printwriter.flush();
byte[] buffer = new byte[2046];
int read;
while ((read = is.read(buffer)) != -1) {
final String output = new String(buffer, 0, read);
);
printwriter.close();
}
});
}
Log.e("message", "message send");
} catch (UnknownHostException e2) {
e2.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
Log.d("Time out", "Time");
}

Categories

Resources