I tried to write a simple server for an app that user can write a message from PC using telnet to IP and port. IT works just fine and it can show the
The problem is, when user closes telnet window (CMD window in PC, there is where user connects to app) the app stops.
Is there a way to prevent this behaviour? Here is my code:
//Defined in Activity class
//Sockets, servers, clients and stuff
public java.net.ServerSocket MyServerSocket;
public String IpAddress = "";
public int Port = 12345;
public Handler UpdateConversationHandler;
public Thread ServerThread = null;
Nested classes inside the Activity class:
class ServerThread implements Runnable{
public final String IpAddress;
public final int Port;
public ServerThread(String ipAddress, int port)
{
IpAddress = ipAddress;
Port = port;
}
public void run() {
Socket socket = null;
try{
MyServerSocket = new ServerSocket(Port);
} catch (IOException e) {
e.printStackTrace();
}
while(!Thread.currentThread().isInterrupted()){
try{
socket = MyServerSocket.accept();
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class CommunicationThread implements Runnable
{
private Socket clientSocket;
private BufferedReader input;
public CommunicationThread(Socket clientSocket)
{
this.clientSocket = clientSocket;
try{
this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
} catch (IOException e){
e.printStackTrace();
}
}
public void run() {
while(!Thread.currentThread().isInterrupted()){
try{
String read = input.readLine();
UpdateConversationHandler.post(new UpdateUIThread(read));
} catch (IOException e){
e.printStackTrace();
}
}
}
}
class UpdateUIThread implements Runnable {
private String msg;
public UpdateUIThread(String str) {
this.msg = str;
}
#Override
public void run() {
_textview_info.setText("Client Says: "+ msg );
}
}
I also have this code for onStop method, but it doesn't help!
#Override
protected void onStop() {
super.onStop();
//Closing server socket
try
{
MyServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
And this is the onCreate method, where the server starts:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
_context = this;
//Prepare spinners
_preferences = getSharedPreferences("org.pervasivesystems.nexusmosaic", MODE_PRIVATE);
_preferencesEditor = _preferences.edit();
_spinner_videos = (Spinner) findViewById(R.id.spinner_select_video);
_spinner_ids = (Spinner) findViewById(R.id.spinner_select_id);
populateSpinners();
//Prepare server
IpAddress = getIpAddress();
TextView tvIpAddress = (TextView) findViewById(R.id.textview_ip_address_value);
tvIpAddress.setText(IpAddress);
_textview_info = (TextView) findViewById(R.id.textview_information);
UpdateConversationHandler = new Handler();
ServerThread = new Thread(new ServerThread(IpAddress, Port));
this.ServerThread.start();
}
UPDATE
When I start the app, even before connecting from PC to app using telnet, I get the following message continuesly in LOGCAT:
11-14 15:45:32.460 W/System.err? at java.lang.Thread.run(Thread.java:856)
11-14 15:45:32.460 W/System.err? java.net.SocketException: Socket is closed
11-14 15:45:32.460 W/System.err? at java.net.ServerSocket.checkOpen(ServerSocket.java:362)
11-14 15:45:32.460 W/System.err? at java.net.ServerSocket.accept(ServerSocket.java:120)
11-14 15:45:32.460 W/System.err? at .MainActivity$ServerThread.run(MainActivity.java:233)
Line 233 is refering to this code:
while(!Thread.currentThread().isInterrupted()){
try{
socket = MyServerSocket.accept(); //LINE 233
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
} catch (IOException e) {
e.printStackTrace();
}
I also found out that after closing the telnet window from PC, the UpdateUiThread keeps running.
What is probably happening is that your communication thread is noticing the terminated connection and exits. This is how you wrote it. Im not sure what you want it to do instead...
If you want to do something after the terminated connection, just put some code right after
while(!Thread.currentThread().isInterrupted()){ ... }
Wait for the thread to finish, then do what you want.
Sometimes it helps me to add some system outs throughout threaded code to get a handle of when things are firing off/ending. It will help, trust me.
Try this
do{
if(!Thread.currentThread().isInterrupted()){
try{
socket = MyServerSocket.accept();
if(socket!=null && socket.isConnected()){
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}while(socket!=null && socket.isConnected());
Related
I made a super simple server on my Windows Machine that waits for a client, and when connected, all it does is get a message and prints it to the Console.
When I run a Server code on my computer, and then run another Client application, it works fine. However, when I run the exact same client code(except for a few changes that are necessary) on my Android Phone(connected via USB), it doesn't work.
The IP address for my PC is correct and the port is free, I've been getting this error message:
W/System.err: java.net.ConnectException: failed to connect to /192.168.10.104 (port 1755) from /:: (port 42102): connect failed: ETIMEDOUT (Connection timed out)
My server.java that runs on my PC is
import java.net.*;
import java.io.*;
public class Server {
// Initialize everything
private Socket socket = null;
private ServerSocket server = null;
private DataInputStream in =null;
//constructor with port
public Server(int port) {
try {
server = new ServerSocket(port);
System.out.println("Server started, waiting for Client...");
socket = server.accept();
System.out.println("Client accepted");
in =new DataInputStream(new BufferedInputStream(socket.getInputStream()));
String line = "";
while (!line.equals("Over")) {
try {
line = in.readUTF();
System.out.println(line);
}
catch(IOException e) {
System.out.println(e);
}
}
System.out.println("Closing connection");
//CLosing connections
socket.close(); in .close();
}
catch(IOException e) {
System.out.println(e);
}
}
public static void main(String[] args) {
Server server = new Server(1755);
}
}
This is the client code
import java.io.*;
import java.net.*;
public class MainActivity extends AppCompatActivity {
TextView Message_shower;
EditText text_place;
TextView messageStatus;
Button send_btn;
// Initialize sockets and IO streams
Socket socket = null;
DataOutputStream out = null;
private static final int SERVERPORT = 1755;
private static final String SERVER_IP = "192.168.10.104";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text_place = findViewById(R.id.editText);
messageStatus = findViewById(R.id.messageStatus);
send_btn = findViewById(R.id.send_btn);
// Shows recent sent message
Message_shower = findViewById(R.id.Message_shower);
// Establish a connection
send_btn.setOnClickListener(new View.OnClickListener() {#Override
public void onClick(View view) {
new Sender().execute();
}
});
}
// Close connections
private void onClose() {
try {
if (socket != null) {
out.close();
socket.close();
}
}
catch(IOException e) {
System.out.println(e);
}
}
class Sender extends AsyncTask < Void,
Void,
Integer > {
private Exception e1;
private Exception e2;
String input;
#Override
protected void onPreExecute() {
EditText text_place = findViewById(R.id.editText);
// Takes input from terminal
input = text_place.getText().toString();
Message_shower.setText(input);
System.out.println("Reached here\n");
}
#Override
protected Integer doInBackground(Void...params) {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
// Sends output to the socket
out = new DataOutputStream(socket.getOutputStream());
}
catch(Exception e) {
this.e1 = e;
}
try {
out.writeUTF(input);
} catch(Exception h) {
this.e2 = h;
}
return 1;
}
#Override
protected void onPostExecute(Integer result) {
if (e1 != null) {
e1.printStackTrace();
}
if (e2 != null) {
e2.printStackTrace();
}
TextView txt = findViewById(R.id.messageStatus);
txt.setText("Message Sent");
text_place.setText("");
onClose();
}
}
}
All input is very appreciated, I've tried various ways like turning off the firewall and such but none worked.
I'm trying to send commands from my phone to my computer using Sockets.
I've tryed the answers here:
Android and PC Socket connection
But after some digging i found out that you need to use a Async task so i tryed this:
Using AsyncTask for android network connection
But for some reason my socket times out. Is there a way to find out why? because from the error i can't tell:
The error from Logcat:
And this is the client code:
public class MainActivity extends AppCompatActivity {
private Socket client;
private PrintWriter printwriter;
private EditText textField;
private Button button;
private String message;
private static final int SERVERPORT = ####;
private static final String SERVER_IP = "########";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textField = (EditText) findViewById(R.id.editText1); // reference to the text field
button = (Button) findViewById(R.id.button1); // reference to the send button
}
public void onClick(View view) {
message = textField.getText().toString();
textField.setText(""); // Reset the text field to blank
new AsyncAction().execute();
}
private class AsyncAction extends AsyncTask<String, Void, String> {
protected String doInBackground(String... args) {
try {
System.out.println("background running");
System.out.println(message);
client = new Socket(SERVER_IP, SERVERPORT); // connect to server
System.out.println(client.isConnected());
System.out.println("test");
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.write(message); // write the message to output stream
printwriter.flush();
printwriter.close();
client.close(); // closing the connection
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
I wrote a Server for this in Java and tested it in the emulator.
I had two things to do :
The server IP is "10.0.2.2" if you are using an Android Emulator. LocalHost is de Emulator Virtual Machine.
Your application needs Permission Internet in manifest
Here is the server Code
/**
*
* #author Jean-Pierre
*/
public class SocketServer {
private static final int portnumber = 4444;
public static void main(String[] args) {
SocketServer socketServer = new SocketServer();
socketServer.run();
}
/**
* Reads a String from the client
* Converts it to Uppercase
* and sends it Back.
*/
private void run() {
try {
ServerSocket serverSocket = new ServerSocket(portnumber);
Socket clientSocket = serverSocket.accept();
System.out.println("connected with :" + clientSocket.getInetAddress());
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
InputStreamReader is =
new InputStreamReader(clientSocket.getInputStream());
BufferedReader in =
new BufferedReader(is);
while (true) {
String line = in.readLine();
if (line != null) {
System.out.println("recieved:" + line);
out.println(line.toUpperCase());
}
}
} catch (IOException ex) {
Logger.getLogger(SocketServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I am trying to create a connection between two applications using android. I have tried to use sockets to connect. I have created two application
One which accepts the connection when client wants to connect
and another application that requests to connect.
I have successfully run this code in same manner in pc in java in pc network. Is the way of connecting to android also same?
My server class implementation
public class MainActivity extends AppCompatActivity {
private Button startButton;
private ServerSocket server;
private Socket connection;
private TextView statusText;
private ObjectOutputStream output;
private ObjectInputStream input;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
statusText=(TextView)findViewById(R.id.statusText);
startButton=(Button)findViewById(R.id.startButton);
startButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
startRunning();
}
}
);
}
private void startRunning() {
try{
server=new ServerSocket(8080);
while(true)
{
try{
waitForConnection();
setUpStreams();
whileChatting();
}catch(Exception e){}
}
} catch(Exception e){}
}
public void waitForConnection()
{
setMyStatus("Waiting for client to connect...");
try {
connection= server.accept();
setMyStatus("Now connected to "+ connection.getInetAddress().getHostName());
} catch (IOException e) {
e.printStackTrace();
}
}
public void setUpStreams()
{
try {
output= new ObjectOutputStream(connection.getOutputStream());
output.flush();
input= new ObjectInputStream(connection.getInputStream());
setMyStatus("Streams are now setup. Ready to go...");
} catch (IOException e) {
e.printStackTrace();
}
}
public void whileChatting()
{
setMyStatus("You can now start chatting...");
}
public void setMyStatus(String msg) {
statusText.setText(msg);
}
}
I will use the tasks like async task later. But i am just trying to set up connection in these application.
My client implementation goes like this
public class MainActivity extends AppCompatActivity {
private Button startButton;
private Socket connection;
private TextView statusText;
public ObjectOutputStream output;
public ObjectInputStream input;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
statusText=(TextView)findViewById(R.id.statusText);
startButton=(Button)findViewById(R.id.startButton);
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startRunning();
}
});
}
private void startRunning() {
connectToServer();
setUpStreams();
whileChatting();
}
public void connectToServer()
{
setMyStatus("Connecting to server. Please wait...");
try {
connection= new Socket(InetAddress.getByName("127.0.0.1"),8080);
setMyStatus("Connected to Server."+ connection.getInetAddress().getHostName());
} catch (IOException e) {
e.printStackTrace();
}
}
public void setUpStreams()
{
try {
output= new ObjectOutputStream(connection.getOutputStream());
output.flush();
input= new ObjectInputStream(connection.getInputStream());
setMyStatus("Streams are now setup. Ready to go...");
} catch (IOException e) {
e.printStackTrace();
}
}
public void whileChatting()
{
setMyStatus("You can now start chatting...");
}
public void setMyStatus(String msg) {
statusText.setText(msg);
}
}
The error I got is in the case of client that tries to connect to server
java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.OutputStream java.net.Socket.getOutputStream()' on a null object reference
at com.myapp.client.clientdemo.MainActivity.setUpStreams(MainActivity.java:71)
at com.myapp.client.clientdemo.MainActivity.startRunning(MainActivity.java:46)
at com.myapp.client.clientdemo.MainActivity.access$000(MainActivity.java:16)
at com.myapp.client.clientdemo.MainActivity$1.onClick(MainActivity.java:33)
It's because "connection" was never created. Probably because it failed to connect or it timed out and it moved on to the next code. If it timed out or didn't connect, then you need to catch that exception and retry to connect before moving on with your later code.
Socket can be tricky if you do not catch all the erroneous states they can get into.
simply wrap your try and catch with a while loop until the condition is met like this:
while(!connected & !closed){
try {
connection= new Socket(InetAddress.getByName("127.0.0.1"),8080);
connected = true;
//now it is connected and will exit the loop and continue with other code
} catch (SocketTimeoutException socketTimeoutException) {
//add this for safety
} catch (IOException e) {
e.printStackTrace();
}
}
I have made an application that opens up a socket via a thread and updates based on what is typed. Here is the code:
Server.java:
public class Server {
public static void main(String[] args) throws IOException {
int portNumber = 2392;
boolean listening = true;
System.out.println("Server: Running...");
try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
System.out.println("Server: Connected to Client!");
while (listening) {
new ServerThread(serverSocket.accept()).start();
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection( '" + e.getMessage() + "' );");
} finally {
System.out.println("Server: Disconnecting...");
}
}
}
Server Thread.java:
public class ServerThread extends Thread {
private Socket socket = null;
Scanner reader = new Scanner(System.in);
public ServerThread(Socket socket) {
super("ServerThread");
this.socket = socket;
}
public void run() {
System.out.println("Ruasd");
try (PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
String outputLine = "";
while (!outputLine.equals("Disconnect")) {
outputLine = reader.nextLine();
out.println(outputLine);
}
socket.close();
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client.java:
public class MainActivity extends Activity {
private Socket socket;
private TextView status;
private BufferedReader in;
private Handler mHandler;
private static final int SERVERPORT = 2392;
private static final String SERVER_IP = "...ip#...";
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_vitals);
status = (TextView) findViewById(R.id.text_status);
new Thread(new CommunicationThread()).start();
}
#Override
protected void onStop() {
super.onStop();
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class CommunicationThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
final String fromServer = in.readLine();
System.out.println("Server: " + fromServer);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// This code will always run on the UI thread, therefore is safe to modify UI elements.
status.setText(fromServer);
}
});
if (fromServer.equals("Disconnect."))
break;
}
} catch (IOException e) {
e.printStackTrace();
}
It works perfectly the first time and outputs to the status TextView correctly. However, when I restart the application, it outputs every other word. For instance, If I type "Hey" "Hi "You" "How", I will see "Hi" and "How" in the TextView the second time I start the application.
What's really odd to me is that when I do System.out.println("Server: " + fromServer) it is outputting all values. Any suggestions are greatly appreciated.
Ok I think I found the problem (got it working for me, that is). In your CommunicationThread, you didn't have a while loop. Also, you need to iterate the server's input until it is null. See below:
class CommunicationThread implements Runnable {
#Override
public void run() {
try {
// keep the connection alive.
while (true) {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String fromServer;
// get server messages until there are none
while ((fromServer = in.readLine()) != null) {
System.out.println("Server: " + fromServer);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// This code will always run on the UI thread, therefore is safe to modify UI elements.
status.setText(fromServer);
}
});
if (fromServer.equals("Disconnect."))
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Please get back to me on how it works out :)
I've tried out almost everything.
Forwarding from ADB Shell using adb forward TCP:12345 TCP:12345
Using 10.0.2.2 (without forwarding) to listen to my host machine
Setting the INTERNET permission in the manifest
Setting the thread policy to permit all functions
I'm running my client java program in 12345 port and I have a ServerSocket in the Android program that listens over the same port. But when I run my client (after running the server program on the emulator) and enter the String that I want to transfer, I get the exception saying 'Connection Refused'.
java.net.ConnectException: Connection refused: connect
Here's my server program:
public class MainActivity extends Activity {
TextView tv;
ServerSocket ss = null;
String mClientMsg = "";
Thread myCommsThread = null;
public static final int SERVERPORT = 12345;
protected static final int MSG_ID = 0x1337;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = new TextView(this);
tv.setText("Nothing from client yet");
setContentView(tv);
this.myCommsThread = new Thread(new CommsThread());
this.myCommsThread.start();
}
#Override
protected void onStop() {
super.onStop();
try {
// make sure you close the socket upon exiting
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Handler myUpdateHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ID:
// TextView tv = (TextView) findViewById(R.id.TextView01);
tv.setText(mClientMsg);
setContentView(tv);
break;
default:
break;
}
super.handleMessage(msg);
}
};
class CommsThread implements Runnable {
public void run() {
Socket s = null;
try {
ss = new ServerSocket(SERVERPORT);
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
Message m = new Message();
m.what = MSG_ID;
try {
if (s == null)
s = ss.accept();
BufferedReader input = new BufferedReader(
new InputStreamReader(s.getInputStream()));
String st = null;
st = input.readLine();
mClientMsg = st;
myUpdateHandler.sendMessage(m);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
My Java client program is as follows:
public class TCPSender {
public static void main(String args[]) {
try {
DataInputStream dis = new DataInputStream(System.in);
System.out.println("Enter the file name:");
#SuppressWarnings("deprecation")
String f = dis.readLine();
File f1 = new File(f);
FileReader fr = new FileReader(f1);
Socket s = new Socket("127.0.0.1", 12345);
PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
pw.println(f);
int c = 0;
while ((c = fr.read()) != -1)
pw.println(c);
System.out.println("File content are sent....");
fr.close();
s.close();
} catch (Exception e) {
System.out.println("" + e);
}
}
}