I've a simple client and server on android. Everything works fine except when I close the client app then the server stops working the app closes.
I think it's about not closing the socket. But when I close the socket in the client the server still stops working.
I'm running a thread on the server. This is my server code:
this.serverThread = new Thread(new ServerThread());
this.serverThread.start();
}
#Override
protected void onStop() {
super.onStop();
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SERVERPORT);
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.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;
private boolean feedback = false;
public updateUIThread(String str) {
msg = str;
}
#Override
public void run() {
parseCommand();
if(feedback)
{
textFeedback.setText(msg);
feedback = false;
}
else
{
textTv.setText(msg);
}
}
if(msg != null)
parseCommand();
and in
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
if(read == null)
{
clientSocket.close();
Log.d("Test","SOCKET CLOSED");
return;
}
updateConversationHandler.post(new updateUIThread(read));
} catch (IOException e) {
e.printStackTrace();
}
}
Related
i Use Socket To communicate between android and wifi its return me OutOfMemory Error When i Trying to disconnect 3 seconds after Sending Data
i have an interface to handle data:
public interface SocketConnections {
public void onSocketConnectionChanged(boolean isConnected, Socket socket);
public void onMessageRecieved(String Message);
public void onMessageSent();
}
SocketClass
public class connectSocket implements Runnable {
public Socket socket;
private DataOutputStream out;
private InputStream in;
private SocketConnections connections;
private static final String TAG = "connectSocket";
public connectSocket(SocketConnections connections) {
this.connections = connections;
}
#Override
public void run() {
connect();
}
private void connect() {
disconnect();
try {
try {
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
socket = new Socket(wsConfig.HOST_ADDRESS, wsConfig.PORT_NUMBER);
socket.setTcpNoDelay(true);
socket.setKeepAlive(true);
if (socket.isConnected()) {
connections.onSocketConnectionChanged(true, socket);
Log.i(TAG, "Connected");
while (socket.isConnected()) {
out = new DataOutputStream(socket.getOutputStream());
in = socket.getInputStream();
String S;
if (in != null) {
while (true) {
byte[] content = new byte[1024];
try {
Thread.sleep(2000);
int bytesRead = in.read(content);
if (bytesRead == -1) {
break;
}
byte[] x = Arrays.copyOfRange(content, 0, bytesRead);
Log.i(TAG, "run: " + x.length);
S = Util.fromByteArrayToHexString(x);
connections.onMessageRecieved(S);
} catch (Exception e) {
}
}
}
}
}
} catch (Exception e) {
connections.onSocketConnectionChanged(false, socket);
e.printStackTrace();
}
}
}).start();
} catch (Exception ignored) {
}
} catch (Exception ignored) {
}
}
public void sendData(final byte[] S) {
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(100);
out.write(S);
out.flush();
connections.onMessageSent();
} catch (Exception e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
public void disconnect() {
if (socket != null && socket.isConnected()) {
try {
socket.close();
connections.onSocketConnectionChanged(false, socket);
// Toast.makeText(G.context, "سیستم به سرور متصل نیست.", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
i want to add 3 seconds delay after sending data and Disconnect
like this
public void sendData(final byte[] S) {
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(100);
out.write(S);
out.flush();
connections.onMessageSent();
Thread.sleep(3000);
disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
its return me out of memory error and force close what should i do?
ok so i found my problem and solved it. i'm not sure but i think when i'm trying to sleep thread inside other thread its some how its going to stop itself before start or i don't know whats happens there but when i put sleep in other method and call that in my first thread its works fine. if some one know about it tell us
Sorry for my english. I am trying to create client and server. Now, my logic is like this:
I start app -> start server -> server listening to all messages -> if client sends message to server -> message goes to server -> message received by server -> server needs to send a message to all its customers.
But the server does not do this
** the server needs to send a message to all its customers**
or maybe
the client is not listening to the server.
my question: Why does the client not accept messages from the server?
//Main
//send message
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (sendText.getText().toString().equals("")) {
return;
}
if(chatClientThread==null){
return;
}
chatClientThread.sendMsg(sendText.getText().toString() + "\n");
}
});
//method create server and client, cliend connect to server
createServer(port);
}
public void createServer(int port) {
//create server
ChatServerThread chatServerThread = new ChatServerThread(port);
chatServerThread.start();
//subscribe to server 192.168.31.101 - ip server
createClient("Testov", "192.168.31.101", port);
}
//method for create client
public void createClient(String name, String ipAdress, int SocketServerPORT) {
chatClientThread = new ChatClientThread(
name, ipAdress, SocketServerPORT);
chatClientThread.start();
}
//this is server class
private class ChatServerThread extends Thread {
int SocketServerPORT;
public ChatServerThread(int SocketServerPORT) {
//set port
this.SocketServerPORT = SocketServerPORT;
}
#Override
public void run() {
Socket socket = null;
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
try {
//create server socket
serverSocket = new ServerSocket(SocketServerPORT);
//waite connect
socket = serverSocket.accept();
Log.e("connect", "server side");
//for input and output
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
//listener
while(true) {
if (dataInputStream.available() > 0) {
//read line
String newMsg = dataInputStream.readUTF();
//send line to client
dataOutputStream.writeUTF(newMsg);
final String ms = newMsg;
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), ms, Toast.LENGTH_SHORT).show();
}
});
//end thread
dataOutputStream.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
//this is client side
private class ChatClientThread extends Thread {
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
String name;
String dstAddress;
int dstPort;
String msgToSend = "";
boolean goOut = false;
String msgLog = "";
ChatClientThread(String name, String address, int port) {
this.name = name;
dstAddress = address;
dstPort = port;
}
#Override
public void run() {
try {
//set ip adress and port
socket = new Socket(dstAddress, dstPort);
//for get and post data
String mesageFromServer = null;
dataInputStream = new DataInputStream(socket.getInputStream());
while(!goOut) {
//wait message from server
mesageFromServer = dataInputStream.readUTF();
//output
Log.e("client", mesageFromServer);
final String ms = mesageFromServer;
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), ms, Toast.LENGTH_SHORT).show();
}
});
msgToSend = "";
}
} catch (UnknownHostException e) {
e.printStackTrace();
final String eString = e.toString();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, eString, Toast.LENGTH_LONG).show();
Log.e("errror", eString);
}
});
} catch (IOException e) {
e.printStackTrace();
final String eString = e.toString();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, eString, Toast.LENGTH_LONG).show();
Log.e("errror", eString);
}
});
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private void sendMsg(String msg){
try {
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeUTF(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
private void disconnect(){
goOut = true;
}
}
I'm beginer in android and i'm trying develop a connection TCP server.
I have this class:
public class JavaTCPServer {
public static void send(String aMessage) {
final String msg = aMessage;
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Socket socket = null;
try {
ServerSocket serverSocket = GlobalSingleton.getInstance().getServerSocket();
socket = serverSocket.accept();
PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
printWriter.println(msg);
printWriter.flush();
printWriter.close();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
socket = null;
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
});
thread.start();
}
}
private ServerSocket serverSocket; //Created in GlobalSingleton Class...
try {
serverSocket = new ServerSocket(Constantes.TCP_PORT);
} catch (IOException e) {
e.printStackTrace();
}
I can send message normally in the first time, but when i try to send message the second time the software remains in line: socket = serverSocket.accept(); and the message in printWriter.println(msg) is not sent.
Additional Information
When i kill the app in settings and open i can send once.
Any questions don't hesitate ask me.
Thanks for all!
Your code only accepts one connection, processes it, and then exits. It does not behave as you have described.
You need a loop.
You also need to start a separate thread to handle each connection.
And calling a method that accepts connections send() is inside out and back to front.
I solved my own problem.
I wrote my class as the follow bellow code:
public class JavaTCPServer {
private ServerSocket serverSocket;
private String message;
private Handler updateConversationHandler;
private Thread serverThread = null;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public ServerSocket getServerSocket() {
return serverSocket;
}
public void setServerSocket(ServerSocket serverSocket) {
this.serverSocket = serverSocket;
}
public JavaTCPServer() {
setUpdateConversationHandler(new Handler());
this.serverThread = new Thread(new ServerThread());
this.serverThread.start();
}
public Handler getUpdateConversationHandler() {
return updateConversationHandler;
}
public void setUpdateConversationHandler(Handler updateConversationHandler) {
this.updateConversationHandler = updateConversationHandler;
}
class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(Constantes.TCP_PORT);
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.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;
private String messageSend;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try {
this.setInput(new BufferedReader(new InputStreamReader(
this.clientSocket.getInputStream())));
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
Central central = GlobalSingleton.getInstance()
.get_current_central();
if (central != null) {
if ((central.getStep() <= central.getObjetivo()) &&
(central.getStep() == 99)){
try {
messageSend = getMessage();
PrintWriter printWriter = new PrintWriter(
clientSocket.getOutputStream(), true);
printWriter.println(messageSend);
printWriter.flush();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
printWriter.println(Constantes.EXIT_CONFIG);
printWriter.flush();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
central.setStep(central.getStep() + 1);
}
}
/*
* try { String read = input.readLine();
* updateConversationHandler.post(new updateUIThread(read)); }
* catch (IOException e) { e.printStackTrace(); }
*/
}
}
public BufferedReader getInput() {
return input;
}
public void setInput(BufferedReader input) {
this.input = input;
}
}
}
With this class you can send and receive tcp messages all the time.
Thanks for all help!
Serversocket.accept() function is for accepting a new client and connecting with the client, for messages you need to use DataInputStream() and DataOutputStream() after connecting with the server. This happens because for the first time server accepts the new client and process further but after this it does not get a new connection and it waits for new connection at serversocket.accept().
I use these codes for communicating between devices. If i close or kill the client app, the server app gets thousands of useless data. The textView in the server side is full of this: Client says: null. If i close the client twice, the server stops with StackOverFlowError. How can i make the code to dont send this null values when the app stops? Or can i filter the server side to do nothing when getting this data?
Client:
public class Client extends Activity {
private Socket socket;
private static final int SERVERPORT = 5000;
private static final String SERVER_IP = "10.0.2.2";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Thread(new ClientThread()).start();
}
public void onClick(View view) {
try {
EditText et = (EditText) findViewById(R.id.EditText01);
String str = et.getText().toString();
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
out.println(str);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
Server:
public class Server extends Activity {
private ServerSocket serverSocket;
Handler updateConversationHandler;
Thread serverThread = null;
private TextView text;
public static final int SERVERPORT = 1599;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
text = (TextView) findViewById(R.id.text2);
updateConversationHandler = new Handler();
this.serverThread = new Thread(new ServerThread());
this.serverThread.start();
}
#Override
protected void onStop() {
super.onStop();
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SERVERPORT);
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.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() {
text.setText(text.getText().toString()+"Client Says: "+ msg + "\n");
}
}
}
I think you should use a delimiter character, to tell the Server your Client it's about to die. Add that character of code in onPause method of your Android Activity/Fragment.
Then in your Server, just get the String or byte and compare it against your Delimiter String/Character and stop the Server listening for the Connection.
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
updateConversationHandler.post(new updateUIThread(read));
} catch (IOException e) {
e.printStackTrace();
}
}
The problem is here. You aren't checking the result of readLine() for null. If it returns null, the peer has closed the connection and you should do likewise, and exit this loop. You can probably get rid of the isInterrupted() test as well.
Also, if you get any IOException other that a read timeout when reading from a socket, the connection is dead and you must close the socket and exit your loop.
I have a simple connection activity:
package com.example.conn08;
import ...;
public class MainActivity extends Activity
{
public static Socket clientSocket;
public static DataOutputStream outToServer;
public static PrintWriter outTest;
public static BufferedReader inToServer;
With PrintWriter outTest I test server's availability:
If the user has no Internet, or the server doesn't work, I put Thread on a pause with Boolean shouldContinue.
private Thread mThread;
private final Object lock = new Object();
private Boolean shouldContinue = true;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mThread = new Thread(new Runnable()
{
public void run()
{
while (true)
{
synchronized(lock)
{
try
{
lock.wait(); // lock the Thread
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
while (shouldContinue)
{
try
{
final String data = inToServer.readLine();
if (data != null)
{
Log.v("data", data);
runOnUiThread(new Runnable()
{
#Override
public void run()
{
String put[] = data.split("#");
//Data parsing
}
});
}
}
catch (IOException e)
{
e.printStackTrace();
}
Check on availability of the server:
try {
if(clientSocket.getInputStream().read() == -1)
{
Log.v("Connection: ", "lost");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
});
mThread.start();
Connect();
}
public void Connect()
{
shouldContinue = true;
try
{
clientSocket = new Socket();
clientSocket.connect(new InetSocketAddress("localhost", 15780), 30000);
outToServer = new DataOutputStream(clientSocket.getOutputStream());
inToServer = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
outTest = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(clientSocket.getOutputStream())), true);
synchronized(lock)
{
lock.notify();
}
sendUTF("3#kokoko"); //send the message!
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static void sendUTF(String str)
{
try
{
byte[] buf = str.getBytes("UTF-8");
outToServer.write(buf, 0, buf.length);
outToServer.writeBytes("\n");
outToServer.flush();
}
catch (IOException e)
{
e.printStackTrace();
outServ.setText("Нет соединения!");
}
}
}
Problem in that when I don't use the
if(clientSocket.getInputStream().read() == -1)
And send data to server like here:
sendUTF("3#kokoko");
All is fine, but if I use it, on server I see this message like
"#kokoko" - I lose the first character of the message and my socket is crushed! Help me please