Client only socket programming in android - java

I would like to open a TCP connection to send data to an ip address in an android application. Every socket programming article/thread I find shows both client and server side code (often the chat program). Is it possible to just have the client code running on an android device and send arbitrary data to, for example, google's IP address? Right now I am using the code from this thread (highest upvoted answer) Android Client socket , how to read data? in a class that extends AsynchTask like this:
public class InternetTask extends AsyncTask<Void, Integer, Void> {
public static final int BUFFER_SIZE = 2048;
private Socket socket = null;
private PrintWriter out = null;
private BufferedReader in = null;
private int port = 80;
private String host = null;
private static final String TAG="sure2015test";
public InternetTask(String host,int port) {
this.host=host;
this.port=port;
}
#Override
protected Void doInBackground(Void... args) {
connectWithServer();
Log.i(TAG, "Connected");
sendDataWithString("hello");
Log.i(TAG, "Sent data");
String response=receiveDataFromServer();
Log.i(TAG,response);
disConnectWithServer();
return null;
}
private void connectWithServer() {
try {
if (socket == null) {
socket = new Socket(this.host, this.port);
out = new PrintWriter(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
} catch (IOException e) {
Log.i(TAG,"IO Exeception");
e.printStackTrace();
}
}
private void disConnectWithServer() {
if (socket != null) {
if (socket.isConnected()) {
try {
in.close();
out.close();
socket.close();
} catch (IOException e) {
Log.i(TAG,"IO exception disconnecting");
e.printStackTrace();
}
}
}
}
public void sendDataWithString(String message) {
if (message != null) {
connectWithServer();
out.write(message);
out.flush();
}
}
public String receiveDataFromServer() {
try {
String message = "";
int charsRead = 0;
char[] buffer = new char[BUFFER_SIZE];
Log.i(TAG,"Message before: "+message);
while ((charsRead = in.read(buffer)) != -1) {
message += new String(buffer).substring(0, charsRead);
Log.i(TAG,message);
}
Log.i(TAG,"Message after: "+message);
disConnectWithServer(); // disconnect server
return message;
} catch (IOException e) {
Log.i(TAG,"IO Error in receiving message");
return "Error receiving response: " + e.getMessage();
}
}
}
And my onCreate method in MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InternetTask task=new InternetTask("74.125.226.159",80);
task.execute();
}
When I run this I get this in the logs:
05-16 00:01:04.368 622-637/? I/sure2015test﹕ Connected
05-16 00:01:04.369 622-637/? I/sure2015test﹕ Sent data
05-16 00:01:04.369 622-637/? I/sure2015test﹕ Message before:
05-16 00:03:04.405 622-637/com.example.connorstein.sockethelloworld I/sure2015test﹕ Message after:
So there were no exceptions when opening a socket on port 80 with the IP of google and no exceptions sending or receiving the data. It looks like I just have no response. Is this expected because the data I sent ("hello") is meaningless? I would think that at least I would get a response saying invalid request or something like that. I also tried sending "GET / HTTP/1.0", but also no response.

Google is responding blank because you aren't sending it a proper HTTP request. Mimic the request of a normal web browser, and you will get a response. HTTP is a protocol built on top of TCP. You need to follow the protocol to get anything useful out of servers.
Example minimal browser header that gets a response:
GET / HTTP/1.1\r\nUser-Agent: curl/7.37.1\r\nHost: www.google.com\r\nAccept: */*\r\n\r\n
Instead of using a web server, consider using an SSH server. An SSH server will send something like...
SSH-2.0-OpenSSH_5.3\r\n
...when you connect. A server that always responds is a lot easier to troubleshoot client code. Note that you might make a sysadmin mad constantly connecting to their ssh server. You may want to set up your own to test against.

Related

Problem in establishing connection in HTTPS in proxy server.(CONNECT Method)

I am developing a proxy server based on java. For simple http request, proxy server is working. But for HTTPS Connection, connection gets timed out. Here are the steps I did. I first read one line from input stream and created a socket connecting Server. After that I gave 200 Status to client. After that I asynchronously read and write between Client Socket and Server socket. But currently this isn't working and connection gets timedout and I couldn't debug the problem.
public class ProxyServer extends Thread {
private String host;
private int port;
private ServerSocket serverSocket;
private InputStream proxyToClientIP;
private OutputStream proxyToClientOP;
private InputStream proxyToServerIP;
private OutputStream proxyToServerOP;
private Socket socket;
private Socket socketFromProxyServer;
ProxyServer(ServerSocket serverSocket, Socket socket) {
this.serverSocket = serverSocket;
this.socket = socket;
this.start();
}
public void run() {
processInputRequest();
}
public void processInputRequest() {
try {
proxyToClientIP = socket.getInputStream();
proxyToClientOP = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(proxyToClientIP));
String hostDetails = reader.readLine();
System.out.println(hostDetails);
boolean isConnect = false;
//Need to parse request and find req type as GET or CONNECT
//As of now we assume it to be Connect request
if (!isConnect) {
processGetRequest();
} else {
processConnectRequest();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void processConnectRequest() {
//Need to get host name from request. Currently Hardcoded for developing purpose
host = "harish-4072";
port = 8383;
try {
socketFromProxyServer = new Socket(host, port);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(proxyToClientOP));
writer.write("HTTP/1.1 200 Connection established\r\n" + "\r\n");
writer.flush();
proxyToServerOP = socketFromProxyServer.getOutputStream();
proxyToServerIP = socketFromProxyServer.getInputStream();
proxyRequest();
} catch (IOException ex) {
System.out.println(ex);
}
}
public void proxyRequest() {
try {
new Thread() {
#Override
public void run() {
try {
byte[] read = new byte[1024];
int in;
System.out.println("Reading");
while ((in = proxyToClientIP.read(read)) != -1) {
proxyToServerOP.write(read, 0, in);
proxyToServerOP.flush();
}
} catch (SocketException e) {
System.out.println(e);
} catch (IOException ex) {
}
}
}.start();
byte[] reply = new byte[1024];
int out;
System.out.println("Writing");
while ((out = proxyToServerIP.read(reply)) != -1) {
proxyToClientOP.write(reply, 0, out);
proxyToClientOP.flush();
}
} catch (IOException ex) {
}
public void processGetRequest() {
//
}
}
I first read one line from input stream and created a socket connecting Server. ... After that I asynchronously read and write between Client Socket and Server socket.
The problem is that you are reading only a single line while you would need to read the full HTTP request header from the client, i.e. everything up to the end of the request header (\r\n\r\n).
Because you fail to do so the unread parts of the HTTP request are forwarded to the server. But the server is expecting the start of the TLS handshake and these data confuse the server. This might result in hanging or aborting, depending on the content of the data and one the kind of server.

Java socket programming: Connection reset despite closing socket?

I am currently coding a simple TCP chat client-server application which works with sockets. A client connects to the server and as soon as it gets accepted, a new worker thread is created to listen for client input. Connecting to the sever (localhost at port 8818) works fine, but as soon as the worker thread starts listening for more client input after the login a java.net.SocketException: Connection reset is thrown (see stack trace below). I am aware that one possible source of this exception can be a socket that hasn't been closed properly or forcefully by either the server or the client. Therefore, my assumption is that I am not handling the closing of my client socket properly which causes the connection to reset.
What I would like to achieve:
The worker listens for client input, as long as this is not null, requests (e.g. a simple login) are processed, otherwise, the socket is closed (see code excerpts below). My client receives a 'Login Successful' message from the server indicating that my handleLogin() function works, but instead of closing the socket after receiving no more input from the client, the server seems to just reset, even though clientSocket.close() is issued after the while loop.
Server.java
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(serverPort);
while (true) {
// Accept connection(s) from new chat client(s)
System.out.println("SERVER: WAITING TO ACCEPT CLIENT CONNECTIONS ...");
Socket clientSocket = serverSocket.accept();
System.out.println("SERVER: CONNECTION ACCEPTED FROM: " + clientSocket);
// Process client request in separate Thread
WorkerThread worker = new WorkerThread(this, clientSocket);
workerList.add(worker);
worker.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
WorkerThread.java
#Override
public void run() {
try {
handleClientSocket();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void handleLogin(OutputStream outputStream, String[] tokens) throws IOException {
if (tokens.length != 3) {
outputStream.write("LOGIN FAILED!\n".getBytes());
return;
}
// Extract username and password from user input
String username = tokens[1];
String password = tokens[2];
if (username.equals("anna") && password.equals("anna")) {
outputStream.write("Login successful!\n".getBytes());
} else {
outputStream.write("Error logging in!\n".getBytes());
}
}
private void handleClientSocket() throws IOException, InterruptedException {
InputStream inputStream = clientSocket.getInputStream();
this.outputStream = clientSocket.getOutputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
// THIS IS WHERE THE EXCEPTION OCCURS AFTER CLIENT HAS LOGGED IN SUCCESSFULLY
while ((line = bufferedReader.readLine()) != null) {
String[] tokens = StringUtils.split(line);
if (tokens.length > 0 && tokens != null) {
String command = tokens[0];
// Evaluate the entered command and handle the request accordingly
if ("login".equalsIgnoreCase(command)) {
handleLogin(outputStream, tokens);
}
// process other commands ...
}
}
clientSocket.close(); // POSSIBLY WORNG WAY OF CLOSING THE CLIENT SOCKET?
}
Client.java
import java.io.*;
import java.net.Socket;
public class Client {
private final String serverName;
private final int serverPort;
private Socket mySocket;
private OutputStream serverOut;
private InputStream serverIn;
public Client(String serverName, int serverPort) {
this.serverName = serverName;
this.serverPort = serverPort;
}
private boolean connect() {
try {
mySocket = new Socket(serverName, serverPort);
serverOut = mySocket.getOutputStream();
serverIn = mySocket.getInputStream();
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
private void login(String username, String password) throws IOException {
String command = "login " + username + " " + password + "\n";
serverOut.write(command.getBytes());
}
public static void main(String[] args) throws IOException {
Client client = new Client("localhost", 8818);
if (client.connect()) {
System.out.println("Connection successful!");
client.login("anna", "anna");
} else {
System.err.println("Connection failed ...");
}
}
}
Stack Trace
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:189)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at WorkerThread.handleClientSocket(WorkerThread.java:70)
at WorkerThread.run(WorkerThread.java:45)
When I test my server with PUTTY (i.e. by connecting to localhost and then issuing commands in PUTTY's terminal), everything works just fine.
I am still fairly new to socket programming, so I also might have a logic flaw here. Any help will be much appreciated as I really would like to continue this project.
Thanks in advance!
The reason of this exception is that you terminated the client once you connected the server, but the server still read something from the stream. The exception occurs. Here is the code I tested:
while (inputStream.available() != 0) {
line = bufferedReader.readLine();
String[] tokens = StringUtils.split(line);
if (tokens.length > 0 && tokens != null) {
String command = tokens[0];
// Evaluate the entered command and handle the request accordingly
if ("login".equalsIgnoreCase(command)) {
handleLogin(outputStream, tokens);
}
// process other commands ...
}
}
change the condition in while loop to check if the inputstream is still available to read.

Java client and python server connection

i am working on an app in android studio and basiclly i need that whenever i clicked a specific button it will create a connection between the java client and python server.
I first checked when u enter the page\activity of the specific button if there is a wifi connection in the phone.
It works fine. then i tried to do this and it didnt work (Important to say that the current code make my phone and my app crash and stop)
simple server:
HOST = '192.168.1.21'
PORT = 9000
def main():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
client_socket, client_address = server_socket.accept()
print 'Connect with ' + client_address[0]
data = client_socket.recv(1024)
print "data :"
print data
print " end"
if data == HOST+"/n":
print 'hi'
else:
i = 0
while i < 15:
print i
i += 1
client_socket.close()
server_socket.close()
if __name__ == '__main__':
main()
this is just to check a connection. it might look strange because of the host +/n in the if . i recently chenged it because i am new to java and dont know how the data is sent. but that is not the problem rn.
public void ButtonClicked(View view) {
EditText editText = findViewById(R.id.edit_text);
final String ip = editText.getText().toString();
Toast.makeText(this, ip, Toast.LENGTH_SHORT).show();
try {
InetAddress host = InetAddress.getByName(ip);
final Client client = new Client(host, 9000);
new Thread(new Runnable() {
public void run() {
try {
client.send(ip);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
client.send(ip);
}
catch (IOException e) {
System.out.println("Caught Exception: " + e.toString());
}
i read that in android studio 3.0 u need to create a thread when u send data.
the client class that u see here :
public class Client
{
private Socket socket = null;
private BufferedReader reader = null;
private BufferedWriter writer = null;
public Client(InetAddress address, int port) throws IOException
{
socket = new Socket(address, port);
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
}
public void send(String msg) throws IOException
{
writer.write(msg, 0, msg.length());
writer.flush();
}
public String recv() throws IOException
{
return reader.readLine();
}
}
it might be just a simple thing that i dont know of but those are the codes and i cant connect to the server. i figured out that the server works fine because if im connecting from the phone to 192.168.1.21 on the net i receive the connection and it does thw little while.
ty for the help - i would like to get the simplest fixes because im new to java.(sorry if there where grammer\ spelling mistakes)
Edit- logcat for the crash
At the end of your log it says NetworkOnMainThread. In your code there is a line client.send(ip) below your seperate thread which is executed at the main thread.

Sending objects through sockets java TCP server to android app

I'm writing a client-server pair where the server is a java TCP server running on Linux and the client is an Android app developed in Android Studio.
I've successfully made a client-server pair that sends Message objects to each other, but when I try to implement similar functionality in my Android app nothing seems to happen.
The Android app works while just sending Strings with the readLine() and println() methods from the BufferedReader and Printwriter classes, but not with the readObject() and writeObject() from ObjectOutput / InputStream classes.
Have also tried writeUnshared() / readUnshared() methods without luck.
//Message.java
package Message;
import java.io.*;
public class Message implements Serializable {
String msg;
String tag;
String username;
private static final long serialVersionUID = 4L;
// Methods.
}
// Reading MessageObjects in Server.java.
#Override
public void run() {
Message message = null;
try {
while ((message = (Message)reader.readObject()) != null) {
// Processing message.
}
}
}
// Sending Message Objects in android App.
public void onClick(View v) {
if(!msgBox.getText().toString().equals("")) {
final String msg;
try {
msg = msgBox.getText().toString();
writer.writeObject(new Message(msg, CLIENT, username));
msgBox.setText("");
writer.flush();
// Updating ui etc.
}
catch (IOException e) {
e.printStackTrace();
}
textBox.smoothScrollBy(textBox.getMaxScrollAmount(), 100);
}
}
// Connection-method in android app, initalizes streams.
private boolean connect(String username, String address, int port) {
boolean connected = false;
try {
server = new Socket(address, port);
InputStreamReader(server.getInputStream());
reader = new ObjectInputStream(server.getInputStream());
writer = new ObjectOutputStream(server.getOutputStream());
writer.writeObject(new Message("!newUser",AUTOMATED,username));
writer.flush();
connected = true;
System.out.println("Connected!");
}
catch (Exception ex) {
ex.printStackTrace();
System.out.println("Cannot Connect!");
connected = false;
// UI-things.
}
if(connected){
// Thread that listens for replies.
listenThread();
}
return connected;
}
You need to create the ObjectOutputStream before the ObjectInputStream, at both ends. Otherwise you can get a deadlock.
Your read loop is incorrect. readObject() doesn't return null at end of stream, so using null as a loop condition doesn't make sense. It can return null any time you send a null. The loop should terminate when EOFException is caught.

TCP client and server

I'm working on a project which expects a TCP client and Server, where server echoes the message back to client. Following is from the assignment:
The server application shall:
Listen for TCP connections on a well known IP address and port
Accept connections initiated on that port
Receive messages from the client and echo them back
Continue to do this until the client drops the connection.
The client application shall:
Establish a connection with the server at its well known IP address and port
Send messages in an asynchronous manner to the server. The format of the message is
of your choice; however, it must contain enough information in order for it to be
recognized on its return from the server.
I have completed the coding for Server, and this is what i've come up with for the client.
My questions:
What does it mean that Server listens for TCP connections on a well known IP and Port In my implementation, i've used ServerSocket which accepts the port server listens on. Did i interpret it correctly?
In my current implementation of TCPClient, client sends messages to Server, but the println() seems to be a blocking call, which makes it Synchronous. What can i do to make my client asynchronous?
For brevity, I havent added the code of TCPServer, let me know if it is needed
UPDATE**
Based on the feedback, i have modified by TCPClient class. After receiving client request, i spawn two threads ReceiveMessage and SendMessage. Doing that gives me following exception:
[Client] Message sent: Message from Client 97
[Client] Message sent: Message from Client 98
[Client] Message sent: Message from Client 99
[Client] Done Sending all the messages
java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at org.chanders.client.ReceiveMessage.run(ReceiveMessage.java:18)
at java.lang.Thread.run(Thread.java:680)
Following is the new Client Code:
public class TCPClient {
Socket clientSocket = null;
OutputStream out = null;
BufferedReader in = null;
String message = "Hello from Client";
int messagecount = 100;
// server credentials
private static final String SERVER_ADDRESS = "localhost";
private static final int SERVER_PORT = 50001;
protected void execute() {
try {
clientSocket = new Socket(SERVER_ADDRESS, SERVER_PORT);
Thread send = new Thread(new SendMessage(clientSocket.getOutputStream()));
Thread receive = new Thread(new ReceiveMessage(clientSocket.getInputStream()));
send.start();
receive.start();
//For server to wait until send and receive threads finish
send.join();
receive.join();
} catch (UnknownHostException uhe) {
System.err.println("Couldnt find host: " + SERVER_ADDRESS);
uhe.printStackTrace();
System.exit(-1);
}catch(IOException ioe) {
System.err.println("Couldnt get I/O: " + SERVER_ADDRESS);
ioe.printStackTrace();
System.exit(-1);
}catch(InterruptedException ie) {
System.err.println("Thread.join failed: ");
ie.printStackTrace();
System.exit(-1);
}
finally {
//cleanup();
}
}
private void cleanup() {
try {
clientSocket.close();
}catch(Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
public static void main(String[] args) {
TCPClient client = new TCPClient();
client.execute();
}
public class SendMessage implements Runnable {
OutputStream out = null;
String message = "Message from Client";
int messageCount = 100;
public SendMessage(OutputStream out) {
this.out = out;
}
public void run() {
PrintWriter writer = new PrintWriter(out);
try {
for (int i = 0; i < messageCount; i++) {
String m = message + " " + i;
writer.println(m);
System.out.println("[Client] Message sent: " + m);
}
System.out.println("[Client] Done Sending all the messages");
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
} finally {
cleanup();
}
}
private void cleanup() {
try {
out.close();
}catch(Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
}
public class ReceiveMessage implements Runnable {
InputStream in = null;
String message;
public ReceiveMessage(InputStream in) {
this.in = in;
}
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
try {
while ((message = reader.readLine()) != null) {
System.out.println("[Client] Received message from Server: "
+ message);
}
System.out.println("[Client] Done Receiving messages from Server");
} catch (Exception e) {
e.printStackTrace();
} finally {
cleanup();
}
}
private void cleanup() {
try {
in.close();
}catch(Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
}
In this context, Asynchronous probably doesn't mean that you can't use println, but that the client must be able to recevie messages while it's sending new ones.
The client should create the socket and then create two threads, one to send messages and the other to recive and print them.
Update
To avoid the exception, use clientSocket.shutdownOutput() instead of closing the output stream.
You could move the send code back to the main thread and keep a separate thread for the receive code or call shutdownOutput() after joining the send thread. Whatever works better for you.
Use a separate thread for each client. When you write something, in the server end , there must be a method which accepts the string. Otherwise it will be blocking. Paste your server code.
Well known ports are port numbers that have been specifically designated for particular protocols, for example 80 is for HTTP and 443 is for HTTPS. Are you meant to be implementing a particular protocol? If you are I would suggest you use the port number for that protocol. Wikipedia has a list of well known port numbers here:
http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
If this is a professional assignment (as opposed to a some homework) then I would strongly recommend the Netty Server, which is basically a NIO client server framework. It significantly simplifies/streamlines the development of this sort.
Make sure to check their documentation as it provides examples implementing exactly the server/client functionality stated in the question.
If this is a homework then this example should provide all necessary details. Please also check Oracle resources.

Categories

Resources