I'm doing a TCP client communication in my application that should communicate in background also. I'm using AsyncTask for connection and receive data and different Thread with Queue for send. It's work fine until I let the phone alone for a while. After about a 5 minutes connection losed. Ping the phone is going well.
I've tried a partial WakeLock but it does nothing.
TcpClient
public class TcpClient {
public static final String TAG = TcpClient.class.getSimpleName();
public static final String SERVER_IP = "192.168.0.1"; //server IP address
public static final int SERVER_PORT = 666;
// message to send to the server
private String mServerMessage;
// sends message received notifications
private OnMessageReceived mMessageListener = null;
private OnConnectionEstablished mConnectionEstablishedListener = null;
// while this is true, the server will continue running
private boolean mRun = false;
// used to send messages
private PrintWriter mBufferOut;
// used to read messages from the server
private BufferedReader mBufferIn;
private BlockingQueue<String> mSendQueue;
private Thread mSendingThread;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TcpClient(OnMessageReceived listener) {
mMessageListener = listener;
mSendQueue = new LinkedTransferQueue<String>();
}
public void setOnConnectionEstablished(OnConnectionEstablished listener) {
mConnectionEstablishedListener = listener;
}
/**
* Sends the message entered by client to the server
*
* #param message text entered by client
*/
public void sendMessage(final String message) {
// Runnable runnable = new Runnable() {
// #Override
// public void run() {
// if (mBufferOut != null) {
// Log.d(TAG, "Sending: " + message);
// mBufferOut.println(message);
// mBufferOut.flush();
// }
// }
// };
// Thread thread = new Thread(runnable);
// thread.start();
try {
mSendQueue.put(message);
} catch (InterruptedException e) {
}
}
/**
* Close the connection and release the members
*/
public void stopClient() {
mRun = false;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
Log.d("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, SERVER_PORT);
try {
//sends the message to the server
mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//receives the message which the server sends back
mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
mSendingThread = new Thread(new Runnable() {
#Override
public void run() {
Boolean running = true;
while (running) {
try {
String msg = TcpClient.this.mSendQueue.take();
Log.d(TAG, "Sending: " + msg);
mBufferOut.println(msg);
mBufferOut.flush();
} catch (InterruptedException e) {
running = false;
Log.d(TAG, "Stop seinding process");
}
}
}
});
mSendingThread.start();
if(mConnectionEstablishedListener != null) {
Log.d("TCP Client", "C: Connection established");
mConnectionEstablishedListener.connectionEstablished(true);
}
//in this while the client listens for the messages sent by the server
while (mRun) {
mServerMessage = mBufferIn.readLine();
if (mServerMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(mServerMessage);
}
}
Log.d("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'");
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
socket.close();
if(mConnectionEstablishedListener != null) {
mConnectionEstablishedListener.connectionEstablished(false);
}
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
if(mConnectionEstablishedListener != null) {
mConnectionEstablishedListener.connectionEstablished(false);
}
}
mSendingThread.interrupt();
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mMessageListener = null;
mConnectionEstablishedListener = null;
mBufferIn = null;
mBufferOut = null;
mServerMessage = null;
}
public interface OnConnectionEstablished {
public void connectionEstablished (Boolean established);
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the Activity
//class at on AsyncTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
public class ConnectTask extends AsyncTask<String, String, TcpClient> {
#Override
protected TcpClient doInBackground(String... message) {
PumpApplication.this.client = new TcpClient(new TcpClient.OnMessageReceived() {
#Override
public void messageReceived(String message) {
if(PumpApplication.this.mMessageReceivedListener != null) {
PumpApplication.this.mMessageReceivedListener.messageReceived(message);
}
}
});
PumpApplication.this.client.setOnConnectionEstablished(new TcpClient.OnConnectionEstablished() {
#Override
public void connectionEstablished(Boolean established) {
if(PumpApplication.this.mConnectionEstablishedListener != null)
PumpApplication.this.mConnectionEstablishedListener.connectionEstablished(established);
}
});
PumpApplication.this.client.run();
return null;
}
#Override
protected void onProgressUpdate(String... values) {
}
}
What is actually happening and how to get it work in background continuously?
Related
I have a TCP client and a TCP server class in my app.
The client sends small strings such as "1|2|" or "1|11|"
Client class
public class TcpClient {
private static final int MAX_DATA_RETRY = 1;
private static final int PING_TIMEOUT = 100;
private ClientThread thread;
private boolean mRun = true;
private PrintWriter mBufferOut;
private String mIPAdress;
private ArrayList<BufferDataItem> messageBuffer = new ArrayList<BufferDataItem>();
private Socket mSocket;
public TcpClient()
{
thread = new ClientThread();
thread.start();
}
private class ClientThread extends Thread {
#Override
public void run() {
while(mRun)
{
if(messageBuffer.size() <= 0)
continue;
BufferDataItem currMessage = messageBuffer.get(0);
currMessage.retryCount++;
if(currMessage.retryCount > MAX_DATA_RETRY)
{
messageBuffer.remove(0);
continue;
}
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(currMessage.ip);
//Log.e("TCP Client", "C: Connecting...");
try {
if(!serverAddr.isReachable(PING_TIMEOUT))
{
//only attempt to connect to devices that are reachable
messageBuffer.remove(0);
continue;
}
//create a socket to make the connection with the server
mSocket = new Socket(serverAddr, TcpManager.SERVER_PORT);
//Log.i("TCP Debug", "inside try catch");
//sends the message to the server
mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream())), true);
String message = currMessage.message;
if (mBufferOut != null && !mBufferOut.checkError()) {
Log.d("TCP SEND", "PUTTING IN BUFFER! " + message);
mBufferOut.println(message);
listener.messageSent(message, currMessage.ip);
messageBuffer.remove(0);
}
mBufferOut.flush();
}
catch (ConnectException e) {
//Connection refused by found device!
//Log.e("TCP", "C: ConnectException ip = "+currMessage.ip, e);
listener.hostUnreachable(currMessage.ip);
continue;
}
catch (Exception e) {
Log.e("TCP", "S: Error", e);
listener.messageSendError(e);
}
finally {
if(mSocket != null)
mSocket.close();
}
}
catch (Exception e) {
Log.e("TCP", "C: Error", e);
listener.messageSendError(e);
continue;
}
}
}
}
/**
* Sends the message entered by client to the server
*
* #param message text entered by client
*/
public void sendMessage(String message) {
BufferDataItem data = new BufferDataItem();
data.message = message;
data.ip = mIPAdress;
messageBuffer.add(data);
}
public void sendMessage(String message, String ip) {
mIPAdress = ip;
BufferDataItem data = new BufferDataItem();
data.message = message;
data.ip = mIPAdress;
messageBuffer.add(data);
}
/**
* Close the connection and release the members
*/
public void stopClient() {
Log.i("Debug", "stopClient");
mRun = false;
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mBufferOut = null;
}
private class BufferDataItem
{
public String message = "";
public int retryCount = 0;
public String ip = "";
}
private OnMessageSent listener = null;
public interface OnMessageSent {
public void messageSent(String message, String ip);
public void hostUnreachable(String ip);
public void messageSendError(Exception e);
}
public void setMessageSentListener(OnMessageSent listener)
{
this.listener = listener;
}
public void removeMessageSentListener()
{
this.listener = null;
}
}
Server Class
public class TcpServer {
private ServerThread thread;
private boolean mRun = true;
private boolean mEnd = false;
public TcpServer()
{
thread = new ServerThread();
thread.start();
}
private class ServerThread extends Thread {
#Override
public void run() {
try {
Boolean end = false;
ServerSocket ss = new ServerSocket(TcpManager.SERVER_PORT);
while (mRun) {
//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();
String remoteIP = s.getRemoteSocketAddress().toString();
int index = remoteIP.indexOf(":");
remoteIP = remoteIP.substring(1,index);
Log.d("TCP READ", "TCP READ: " + st);
if(st != null)
listener.messageReceived(st, remoteIP);
//output.println("Good bye and thanks for all the fish :)");
if(mEnd)
{
s.close();
mRun = false;
}
}
ss.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
//class at on asynckTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message, String ip);
}
private OnMessageReceived listener = null;
public void SetMessageReceivedListener(OnMessageReceived listener)
{
this.listener = listener;
}
public void RemoveMessageReceivedListener()
{
this.listener = null;
}
}
This works fine for the first few times it runs and then but then the Client sends "1|11|" and the the server sets st as null during the readLine.
String st = input.readLine();
Does anyone have any suggestions?
I see two possible reason why the server does not receive valid data after some time.
Server does not close the socket s because the mEnd is never set to true. The client open a new TCP connection for each message. The server creates a socket for the connection but it never close the socket and the server side of the connection remains open. It is a resource leak and it may cause the problem.
The client use the ArrayList<BufferDataItem> messageBuffer. ArrayList is not a thread safe collection and messageBuffer is used from more than one thread. It is safe to use synchronizedList here. See the How do I make my ArrayList Thread-Safe? Another approach to problem in Java? or Concurrent threads adding to ArrayList at same time - what happens?
I am looking for a way to send received data (receive while flag is set) from a socket service to an activity that is bound to the service. What is the best way to do this ? Handlers , AsyncTask or something else ?
this is the SocketClass I am using to start a connection and handle the incoming messages :
class connectSocket implements Runnable {
#Override
public void run() {
running= true;
try {
socket = new Socket(serverAddr, SERVERPORT);
try {
mBufferOut = new ObjectOutputStream(socket.getOutputStream());
mBufferIn = new ObjectInputStream(socket.getInputStream());
while(running){
msg = (Message) mBufferIn.readObject();
}
}
catch (Exception e) {
Log.e("TCP", "S: Error", e);
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
}
Update :
public class SocketService extends Service {
private static final String TAG = "com.oos.kiesa.chat";
public static final String SERVERIP = "192.168.X.X";
public static final int SERVERPORT = 4444;
private ObjectOutputStream mBufferOut;
private ObjectInputStream mBufferIn;
Socket socket;
InetAddress serverAddr;
boolean mRun;
Object msg;
public Integer command;
#Override
public IBinder onBind(Intent intent) {
return myBinder;
}
private final IBinder myBinder = new LocalBinder();
public class LocalBinder extends Binder {
public SocketService getService() {
return SocketService.this;
}
}
#Override
public void onCreate() {
super.onCreate();
}
public void IsBoundable(){
Toast.makeText(this,"is boundable", Toast.LENGTH_LONG).show();
}
public void sendMessage(String message) throws IOException {
if (mBufferOut != null) {
mBufferOut.writeObject(message);
mBufferOut.flush();
}
}
public void sendMessage(Message message) throws IOException {
if (mBufferOut != null) {
mBufferOut.writeObject(message);
mBufferOut.flush();
}
}
public void sendMessage(User user) throws IOException {
if (mBufferOut != null) {
mBufferOut.writeObject(user);
mBufferOut.flush();
}
}
public void sendMessage(int command) throws IOException {
if (mBufferOut != null) {
mBufferOut.writeInt(command);
mBufferOut.flush();
}
}
#Override
public int onStartCommand(Intent intent,int flags, int startId){
super.onStartCommand(intent, flags, startId);
System.out.println("I am in on start");
Runnable connect = new connectSocket();
new Thread(connect).start();
return START_STICKY;
}
public void stopClient() throws IOException{
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mBufferIn = null;
mBufferOut = null;
socket.close();
}
class connectSocket implements Runnable {
#Override
public void run() {
mRun = true;
try {
socket = new Socket(serverAddr, SERVERPORT);
try {
mBufferOut = new ObjectOutputStream(socket.getOutputStream());
mBufferIn = new ObjectInputStream(socket.getInputStream());
while(mRun){
switch(command.intValue()){
case Constants.ADD_MESSAGE:
msg = (Message) mBufferIn.readObject(); // send message to Activity
break;
}
}
}
catch (Exception e) {
Log.e("TCP", "S: Error", e);
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
try {
socket.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
socket = null;
}
}
Some guidance / examples would be greatly appreciated
I am sending you mine, hope it will help :
class SocketRequestHandler extends Thread {
static String EOF = "<EOF>";
TCPResponseModel tcpResponseDS;
Activity activity;
boolean doSkip = false;
String responseStringComplete = "";
Socket clientSocekt;
OutputStream clientSocketOutputStream;
PrintWriter clinetSocketPrintWriter;
DataInputStream clientSocketInputStream;
private SocketRequestHandler(TCPResponseModel tcpResponseDS, Activity activity, SaloonListener listener) {
this.tcpResponseDS = tcpResponseDS;
this.activity = activity;
this.listener = listener;
moreStores = tcpResponseDS.StoresFound;
}
public static SocketRequestHandler pingAll(Activity activity, TCPResponseModel tcpResponseDS, SaloonListener listener) {
SocketRequestHandler requestHandler = new SocketRequestHandler(tcpResponseDS, activity, listener);
requestHandler.start();
return requestHandler;
}
private void closeStreams() {
try {
clientSocekt.close();
clientSocketInputStream.close();
clinetSocketPrintWriter.close();
clientSocketOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
String pingingHost = "URL_TO_PING";
clientSocekt = new Socket(pingingHost, 12000);
clientSocketOutputStream = clientSocekt.getOutputStream();
clinetSocketPrintWriter = new PrintWriter(clientSocketOutputStream);
String firstPing = "{\"RequestId\":" + tcpResponseDS.RequestId + "}<EOF>";
clinetSocketPrintWriter.println(firstPing);
clinetSocketPrintWriter.flush();
byte[] bytes;
String pingStr = "";
clientSocketInputStream = new DataInputStream(clientSocekt.getInputStream());
while (true) {
bytes = new byte[1024];
clientSocketInputStream.read(bytes);
bytes = trim(bytes);
if (bytes.length > 0 && !doSkip) {
String newString = new String(bytes, "UTF-8");
String decoded = pingStr + newString;
pingStr = checkForMessage(decoded);
responseStringComplete += newString;
}
if (doSkip) {
break;
}
}
closeStreams();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.print(responseStringComplete);
}
}
}
To broadcast chat data just do :
msg = (Message) mBufferIn.readObject(); // Do code after this line
Intent localIntent = new Intent("CHAT_MESSAGE");
localIntent.putExtra("message", msg);
LocalBroadcastManager.getInstance(context).sendBroadcast(localIntent);
Now in the activity where you are showing the chat list you can do
class ReceiveMessages extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals("CHAT_MESSAGE")) {
runOnUiThread(new Runnable() {
#Override
public void run() {
String chatMessage = getIntent().getStringExtra("message");
//get data from intent and update your chat list.
}
});
}
}
}
ReceiveMessages myReceiver;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//your code
myReceiver = new ReceiveMessages();
}
#Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver,
new IntentFilter("CHAT_MESSAGE"));
}
#Override
protected void onStop() {
super.onStop();
LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
}
public class AsyncHttpClient {
public AsyncHttpClient() {
}
public static class SocketIORequest {
private String mUri;
private String mEndpoint;
private List<BasicNameValuePair> mHeaders;
public SocketIORequest(String uri) {
this(uri, null);
}
public SocketIORequest(String uri, String endpoint) {
this(uri, endpoint, null);
}
public SocketIORequest(String uri, String endpoint, List<BasicNameValuePair> headers) {
mUri = Uri.parse(uri).buildUpon().encodedPath("/socket.io/1/").build().toString();
mEndpoint = endpoint;
mHeaders = headers;
}
public String getUri() {
return mUri;
}
public String getEndpoint() {
return mEndpoint;
}
public List<BasicNameValuePair> getHeaders() {
return mHeaders;
}
}
public static interface StringCallback {
public void onCompleted(final Exception e, String result);
}
public static interface WebSocketConnectCallback {
public void onCompleted(Exception ex, WebSocketClient webSocket);
}
public void executeString(final SocketIORequest socketIORequest, final StringCallback stringCallback) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
AndroidHttpClient httpClient = AndroidHttpClient.newInstance("android-websockets-2.0");
HttpPost post = new HttpPost(socketIORequest.getUri());
addHeadersToRequest(post, socketIORequest.getHeaders());
try {
HttpResponse res = httpClient.execute(post);
String responseString = readToEnd(res.getEntity().getContent());
if (stringCallback != null) {
stringCallback.onCompleted(null, responseString);
}
} catch (IOException e) {
if (stringCallback != null) {
stringCallback.onCompleted(e, null);
}
} finally {
httpClient.close();
httpClient = null;
}
return null;
}
private void addHeadersToRequest(HttpRequest request, List<BasicNameValuePair> headers) {
if (headers != null) {
Iterator<BasicNameValuePair> it = headers.iterator();
while (it.hasNext()) {
BasicNameValuePair header = it.next();
request.addHeader(header.getName(), header.getValue());
}
}
}
}.execute();
}
private byte[] readToEndAsArray(InputStream input) throws IOException {
DataInputStream dis = new DataInputStream(input);
byte[] stuff = new byte[1024];
ByteArrayOutputStream buff = new ByteArrayOutputStream();
int read = 0;
while ((read = dis.read(stuff)) != -1) {
buff.write(stuff, 0, read);
}
return buff.toByteArray();
}
private String readToEnd(InputStream input) throws IOException {
return new String(readToEndAsArray(input));
}
I am working on an android chat application based on sockets. I am using the following code to implement this:
NetClient.java
public class NetClient {
/**
* Maximum size of buffer
*/
public static final int BUFFER_SIZE = 2048;
private Socket socket = null;
private PrintWriter out = null;
private BufferedReader in = null;
private String host = null;
private int port = 3000;
// private int port;
/**
* Constructor with Host, Port
*
* #param host
* #param port
*/
public NetClient(String host, int port) {
this.host = host;
this.port = port;
}
private void connectWithServer() {
Log.e("Server", "Connecting with server");
try {
if (socket == null) {
System.out.println("Socket is null");
socket = new Socket(this.host, this.port);
out = new PrintWriter(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void disConnectWithServer() {
Log.e("Server", "Disconnecting with server");
if (socket != null) {
if (socket.isConnected()) {
try {
in.close();
out.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void sendDataWithString(String message) {
Log.e("Send data", "Sendind data to server");
if (message != null) {
connectWithServer();
out.write(message);
out.flush();
}
}
public String receiveDataFromServer() {
Log.e("Receive data", "Receivind data from the server");
try {
String message = "";
int charsRead = 0;
char[] buffer = new char[BUFFER_SIZE];
while ((charsRead = in.read(buffer)) != -1) {
message += new String(buffer).substring(0, charsRead);
}
//Log.e("ServerResponse", message);
disConnectWithServer(); // disconnect server
return message;
} catch (IOException e) {
return "Error receiving response: " + e.getMessage();
}
}
}
ChatActivity.java
public class ChatActivity extends Activity {
private EditText edtMsg;
private Button btnSend;
private String serverIpAddress = "192.168.2.250";
private int port = 3000;
private boolean connected = false;
private Handler handler = new Handler();
private BufferedReader in = null;
private PrintWriter out = null;
public static final int BUFFER_SIZE = 2048; // Max. size of buffer
private Socket socket = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
edtMsg = (EditText) findViewById(R.id.edtMessage);
btnSend = (Button) findViewById(R.id.btnSendMessage);
btnSend.setOnClickListener(connectListener);
}
private View.OnClickListener connectListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"clicked",Toast.LENGTH_LONG).show();
Log.e("Button", "Button clicked");
if (!connected) {
if (!serverIpAddress.equals("")) {
Thread cThread = new Thread(new ClientThread());
cThread.start();
}
}
}
};
public class ClientThread implements Runnable {
public void run() {
NetClient nc = new NetClient(serverIpAddress, port);
String message = edtMsg.getText().toString().trim();
Log.e("Msg", message);
nc.sendDataWithString(message);
String response = nc.receiveDataFromServer();
Log.e("Server Response ", response);
}
}
}
I am not able to verify whether the data has been posted to server or not as i am getting unexpected result from the server.
Logcat
E/Server Response﹕ [ 12-01 14:56:01.313 302: 1017 V/qcbassboost ]
I think i am doing some mistake in the use of socket.Please help me to resolve the issue.
I'm developing a android app with Socket connections. I followed a tutorial on the Internet with a sample server and android client (http://myandroidsolutions.blogspot.nl/2012/07/android-tcp-connection-tutorial.html).
the tutorial worked perfectly.
But I'm trying to connect to a Node.js socket io server with same android client contact. I can send messages with it but I can not received while the server sends a ping every second.
Why its not working?
what am I doing wrong?
The Node.js socket io server is working fine, the iPhone version of the app can send and receive.
All ports are open.
Can someone help me please? Thank u!
Source
TCPClient.java
public class TCPClient {
private String serverMessage;
public static final String SERVERIP = "*ip-addres*"; //your computer IP address
public static final int SERVERPORT = 4444;
private OnMessageReceived mMessageListener = null;
private boolean mRun = false;
PrintWriter out;
BufferedReader in;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TCPClient(OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the server
* #param message text entered by client
*/
public void sendMessage(String message){
if (out != null && !out.checkError()) {
out.println(message);
out.flush();
}
}
public void stopClient(){
mRun = false;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
Log.e("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, SERVERPORT);
try {
//send the message to the server
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
Log.e("TCP Client", "C: Sent.");
Log.e("TCP Client", "C: Done.");
//receive the message which the server sends back
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//in this while the client listens for the messages sent by the server
while (mRun) {
serverMessage = in.readLine();
if (serverMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(serverMessage);
}
serverMessage = null;
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
socket.close();
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
//class at on asynckTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}}
ChatActivity.java
public class ChatActivity extends Activity{
private ListView mList;
private ArrayList<String> arrayList;
private MyCustomAdapter mAdapter;
private TCPClient mTcpClient;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
arrayList = new ArrayList<String>();
final EditText editText = (EditText) findViewById(R.id.editText);
Button send = (Button)findViewById(R.id.send_button);
//relate the listView from java to the one created in xml
mList = (ListView)findViewById(R.id.list);
mAdapter = new MyCustomAdapter(this, arrayList);
mList.setAdapter(mAdapter);
// connect to the server
new connectTask().execute("");
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String message = editText.getText().toString();
//add the text in the arrayList
arrayList.add("c: " + message);
//sends the message to the server
if (mTcpClient != null) {
mTcpClient.sendMessage(message);
}
//refresh the list
mAdapter.notifyDataSetChanged();
editText.setText("");
}
});
}
public class connectTask extends AsyncTask<String,String,TCPClient> {
#Override
protected TCPClient doInBackground(String... message) {
//we create a TCPClient object and
mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
#Override
//here the messageReceived method is implemented
public void messageReceived(String message) {
//this method calls the onProgressUpdate
publishProgress(message);
}
});
mTcpClient.run();
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
//in the arrayList we add the messaged received from server
arrayList.add(values[0]);
// notify the adapter that the data set has changed. This means that new message received
// from server was added to the list
mAdapter.notifyDataSetChanged();
}
}
}
Node JS Server
var net = require('net');
var mysql = require('mysql');
var colorize = require('colorize');
var cconsole = colorize.console;
var clients = [];
var count = 0;
var messages = [];
function create_id()
{
return count += 1;
}
setInterval(function()
{
for(i = 0; i < clients.length; i++)
{
var client = clients[i];
var params = {};
params.type = "ping";
if(client.socket.write(JSON.stringify(params)))
{
console.log("ping send");
}
else
{
clients.splice(i, 1);
}
}
}, 1000);
var server = net.createServer(function( socket )
{
cconsole.log("#red[Client connected to the server with ip: " + socket.remoteAddress+"]");
socket.on("error",function(error)
{
console.log("error" + error);
});
socket.on("close",function()
{
cconsole.log("#red[Client has disconnected]");
});
socket.on("data",function(data)
{
try
{
var packet = JSON.parse(data);
if(packet.type == "register")
{
var client = [];
client.socket = socket;
client.clientID = create_id();
client.username = packet.username;
messages[packet.username] = [];
clients.push(client);
var params = {};
params.type = "register";
params.clientID = client.clientID;
socket.write(JSON.stringify(params));
console.log("Registered client : " + params.clientID);
}
if(packet.type == "online")
{
var params = {};
var identifiers = [];
for(i = 0; i < clients.length; i++)
{
identifiers.push(clients[i].clientID);
}
params.type = "online";
params.clients = identifiers;
socket.write(JSON.stringify(params));
}
if(packet.type == "message")
{
var client = packet.sender;
var recipient = packet.recipient
for(i = 0; i < clients.length; i++)
{
if(clients[i].clientID.toString() == recipient.toString())
{
var params = {}
params.type = "message";
params.sender = packet.sender;
params.recipient = packet.recipient;
params.message = packet.message;
clients[i].socket.write(JSON.stringify(params));
console.log("Wrote message " + params.message + " from sender " + params.sender + " to recipient " + recipient)
return;
}
}
console.log("Recipient was not valid");
}
}
catch(e)
{
cconsole.log(e.message);
}
});
});
server.listen(8124,"<Server IP>", function()
{
//'listening' listener
cconsole.log('Server is listening for incoming connections');
});
Check the Endian-ness of your client and server programs. Your Android app may be sending things in Network Byte Order (Big Endian) while your server is expecting them in Little Endian.
If this is the case, you should make both of your clients transmit with the same byte order, e.g. by using a specific serializer that deals in the correct byte order.
while (mRun) {
serverMessage = in.readLine();
// check if you get a message here..
if (serverMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(serverMessage);
}
serverMessage = null;
}
try to log from the comment to see if you actually get something
I'm working on programming a live support chatting here, but the problem I faced is how to this server I made is receiving only one client to chat with.
can any pro explain to me to make the server receive more than one client at same time ?
and there is another problem which is :
If I close the chat activity then come back to make new chat through the application, the server couldn't response to it.
any suggestion please ...
Server Side:
public class TCPServer extends Thread {
public static final int SERVERPORT = 7777;
private boolean running = false;
private PrintWriter mOut;
private OnMessageReceived messageListener;
public static void main(String[] args) {
//opens the window where the messages will be received and sent
ServerBoard frame = new ServerBoard();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
/**
* Constructor of the class
* #param messageListener listens for the messages
*/
public TCPServer(OnMessageReceived messageListener) {
this.messageListener = messageListener;
}
/**
* Method to send the messages from server to client
* #param message the message sent by the server
*/
public void sendMessage(String message){
if (mOut != null && !mOut.checkError()) {
mOut.println(message);
mOut.flush();
}
}
#Override
public void run() {
super.run();
running = true;
try {
System.out.println("S: Connecting...");
//create a server socket. A server socket waits for requests to come in over the network.
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
//create client socket... the method accept() listens for a connection to be made to this socket and accepts it.
Socket client = serverSocket.accept();
System.out.println("S: Receiving...");
try {
//sends the message to the client
mOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);
//read the message received from client
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
//in this while we wait to receive messages from client (it's an infinite loop)
//this while it's like a listener for messages
while (running) {
String message = in.readLine();
if (message != null && messageListener != null) {
//call the method messageReceived from ServerBoard class
messageListener.messageReceived("Student: "+message);
}
}
} catch (Exception e) {
System.out.println("S: Error");
e.printStackTrace();
} finally {
client.close();
System.out.println("S: Done.");
}
serverSocket.close();
} catch (Exception e) {
System.out.println("S: Error");
e.printStackTrace();
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the ServerBoard
//class at on startServer button click
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
for the client I separate them into two activities :
public class TCPMainActivity extends Activity
{
private ListView mList;
private ArrayList<String> arrayList;
private MyCustomAdapter mAdapter;
private TCPClient mTcpClient;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.tcpmain);
arrayList = new ArrayList<String>();
final EditText editText = (EditText) findViewById(R.id.editText);
Button send = (Button)findViewById(R.id.send_button);
//relate the listView from java to the one created in xml
mList = (ListView)findViewById(R.id.list);
mAdapter = new MyCustomAdapter(this, arrayList);
mList.setAdapter(mAdapter);
// connect to the server
new connectTask().execute("");
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String message = editText.getText().toString();
//add the text in the arrayList
arrayList.add("Student: " + message);
//sends the message to the server
if (mTcpClient != null) {
mTcpClient.sendMessage(message);
}
//refresh the list
mAdapter.notifyDataSetChanged();
editText.setText("");
}
});
}
public class connectTask extends AsyncTask<String,String,TCPClient> {
#Override
protected TCPClient doInBackground(String... message) {
//we create a TCPClient object and
mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
#Override
//here the messageReceived method is implemented
public void messageReceived(String message) {
//this method calls the onProgressUpdate
publishProgress(message);
}
});
mTcpClient.run();
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
//in the arrayList we add the messaged received from server
arrayList.add("Managment: "+values[0]);
// notify the adapter that the data set has changed. This means that new message received
// from server was added to the list
mAdapter.notifyDataSetChanged();
}
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all courses
}
}
protected void onStop() { // TODO Auto-generated method stub
//mTcpClient.stopClient();
Log.e("TCP Client", "Stooped");
super.onStop();
}
protected void onStart() { // TODO Auto-generated method stub
super.onStart();
}
protected void onResume() { // TODO Auto-generated method stub
super.onResume();
//new connectTask().execute("");
}
/* public void onDestroy() { // TODO Auto-generated method stub
super.onDestroy();
}
*/
}
the second one is :
public class TCPClient {
private String serverMessage;
public static final String SERVERIP = "192.168.0.102"; //your computer IP address
public static final int SERVERPORT = 7777;
private OnMessageReceived mMessageListener = null;
private boolean mRun = false;
PrintWriter out;
BufferedReader in;
Socket socket;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TCPClient(OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the server
* #param message text entered by client
*/
public void sendMessage(String message){
if (out != null && !out.checkError()) {
out.println(message);
out.flush();
}
}
public void stopClient(){
mRun = false;
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
mRun = true;
try {
if (socket != null)
socket.close();
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
Log.e("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
socket = new Socket(serverAddr, SERVERPORT);
try {
//send the message to the server
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
Log.e("TCP Client", "C: Sent.");
Log.e("TCP Client", "C: Done.");
//receive the message which the server sends back
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//in this while the client listens for the messages sent by the server
while (mRun) {
serverMessage = in.readLine();
if (serverMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(serverMessage);
}
serverMessage = null;
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
socket.close();
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
//class at on asynckTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
thanking you in advance.