I am trying create a Server-Client chatting application using Java Socket on Android platform with Wifi P2P Connection for my college's thesis. The app will allow the Server to create a new Chat Room and the Client will join the Chat Room.
However, it always failed to send and receive messages when the first time Server and Client being on the Chat Room. It will success to send and receive messages when the Server and Client leave the Chat Room and create a new Chat Room.
There are my source code for send and receive message :
SendMessageServer.java
public class SendMessageServer extends AsyncTask<Message, Message, Message> {
private static final String TAG = "SendMessageServer";
private Context mContext;
private static final int serverPort = 4446;
private boolean isMine;
public SendMessageServer(Context context, boolean mine){
mContext = context;
isMine = mine;
}
@Override
protected Message doInBackground(Message... messages) {
// Display Message Before Sending
publishProgress(messages);
// Send Message to Client
try {
ArrayList<InetAddress> listClients = ServerThread.clients;
for(InetAddress addr : listClients) {
if(messages[0].getSenderAddress()!=null && addr.getHostAddress().equals(messages[0].getSenderAddress().getHostAddress())) {
return messages[0];
}
Socket socket = new Socket();
socket.setReuseAddress(true);
socket.bind(null);
Log.v(TAG,"Connect to Client: " + addr.getHostAddress());
socket.connect(new InetSocketAddress(addr, serverPort));
Log.v(TAG,"Connect to " + addr.getHostAddress() + " Success");
OutputStream outputStream = socket.getOutputStream();
new ObjectOutputStream(outputStream).writeObject(messages[0]);
Log.v(TAG, "Write to "+ addr.getHostAddress() + " Success");
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
Log.v(TAG, "Send Message Server Error");
}
return messages[0];
}
@Override
protected void onProgressUpdate(Message... values) {
super.onProgressUpdate(values);
if(isActivityRunning(MainMenu.class)) {
ChatActivity.refreshList(values[0], isMine);
}
}
@Override
protected void onPostExecute(Message result) {
super.onPostExecute(result);
}
@SuppressWarnings("rawtypes")
public Boolean isActivityRunning(Class activityClass) {
ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (ActivityManager.RunningTaskInfo task : tasks) {
if (activityClass.getCanonicalName().equalsIgnoreCase(task.baseActivity.getClassName())) {
return true;
}
}
return false;
}
}
SendMessageClient.java
public class SendMessageClient extends AsyncTask<Message, Message, Message> {
private static final String TAG = "SendMessageClient";
private Context mContext;
private static final int serverPort = 4445;
private InetAddress mServerAddress;
public SendMessageClient(Context context, InetAddress serverAddress){
mContext = context;
mServerAddress = serverAddress;
}
@Override
protected Message doInBackground(Message... messages) {
// Display Message Before Sending
publishProgress(messages);
// Send the message
Socket socket = new Socket();
try {
socket.setReuseAddress(true);
socket.bind(null);
socket.connect(new InetSocketAddress(mServerAddress, serverPort));
Log.v(TAG, "Connect to Server : " + mServerAddress.getHostAddress() + " Success");
OutputStream outputStream = socket.getOutputStream();
new ObjectOutputStream(outputStream).writeObject(messages[0]);
Log.v(TAG, "Send Message Client Success");
} catch (IOException e) {
e.printStackTrace();
Log.v(TAG, "Send Message Client Error");
} finally{
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
Log.v(TAG, "Send Message Client Error");
}
}
}
}
return messages[0];
}
@Override
protected void onProgressUpdate(Message... messages) {
super.onProgressUpdate(messages);
if(isActivityRunning(MainMenu.class)){
ChatActivity.refreshList(messages[0], true);
}
}
@Override
protected void onPostExecute(Message result) {
super.onPostExecute(result);
}
@SuppressWarnings("rawtypes")
public Boolean isActivityRunning(Class activityClass) {
ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (ActivityManager.RunningTaskInfo task : tasks) {
if (activityClass.getCanonicalName().equalsIgnoreCase(task.baseActivity.getClassName())) {
return true;
}
}
return false;
}
}
ReceiveMessageServer.java
public class ReceiveMessageServer extends AbstractReceiver {
private static final String TAG = "ReceiveMessageServer";
private static final int serverPort = 4445;
private Context mContext;
private ServerSocket serverSocket;
public ReceiveMessageServer(Context context){
mContext = context;
}
@Override
protected Void doInBackground(Void... params) {
try {
serverSocket = new ServerSocket(serverPort);
while(true) {
Socket clientSocket = serverSocket.accept();
InputStream inputStream = clientSocket.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
Message message = (Message) objectInputStream.readObject();
// Add Sender InetAddress to Message
InetAddress senderAddress = clientSocket.getInetAddress();
message.setSenderAddress(senderAddress);
clientSocket.close();
publishProgress(message);
}
} catch (IOException e) {
e.printStackTrace();
Log.v(TAG, "Receive Message Failed : IOException");
} catch (ClassNotFoundException e) {
e.printStackTrace();
Log.v(TAG, "Receive Message Failed : ClassNotFoundException");
}
return null;
}
@Override
protected void onCancelled() {
try {
serverSocket.close();
Log.v(TAG, "Server Socket Close Success");
} catch (IOException e) {
e.printStackTrace();
Log.v(TAG, "Server Socket Close Failed");
}
super.onCancelled();
}
@Override
protected void onProgressUpdate(Message... values) {
super.onProgressUpdate(values);
playNotification(mContext, values[0]);
// Check Message Type exclude Text Message
int type = values[0].getmType();
if(type == Message.audioMessage || type == Message.fileMessage) {
values[0].saveByteArrayToFile(mContext);
}
new SendMessageServer(mContext, false).executeOnExecutor(THREAD_POOL_EXECUTOR, values);
}
}
ReceiveMessageClient.java
public class ReceiveMessageClient extends AbstractReceiver {
private static final String TAG = "ReceiveMessageClient";
private static final int serverPort = 4446;
private Context mContext;
private ServerSocket socket;
public ReceiveMessageClient(Context mContext) {
this.mContext = mContext;
}
@Override
protected Void doInBackground(Void... params) {
try {
socket = new ServerSocket(serverPort);
socket.setReuseAddress(true);
while (true) {
Socket destinationSocket = socket.accept();
InputStream inputStream = destinationSocket.getInputStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
ObjectInputStream objectInputStream = new ObjectInputStream(bufferedInputStream);
Message message = (Message) objectInputStream.readObject();
destinationSocket.close();
publishProgress(message);
}
} catch (IOException e) {
e.printStackTrace();
Log.v(TAG, "Receive Message Client Failed : IOException");
} catch (ClassNotFoundException e) {
e.printStackTrace();
Log.v(TAG, "Receive Message Client Failed : ClassNotFoundException");
}
return null;
}
@Override
protected void onCancelled() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
super.onCancelled();
}
@Override
protected void onProgressUpdate(Message... values) {
super.onProgressUpdate(values);
playNotification(mContext, values[0]);
/* Check if the Message Contains Audio/Video/File
* If true, Save to External Storage
*/
int type = values[0].getmType();
if (type == Message.audioMessage || type == Message.fileMessage){
values[0].saveByteArrayToFile(mContext);
}
if (isActivityRunning(MainMenu.class)){
ChatActivity.refreshList(values[0], false);
}
}
public Boolean isActivityRunning(Class activityClass) {
ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (ActivityManager.RunningTaskInfo task : tasks) {
if (activityClass.getCanonicalName().equalsIgnoreCase(task.baseActivity.getClassName()))
return true;
}
return false;
}
}
The AbstractReceiver class is only for notification so i think the problem just come from those 4 class.
This is the Logcat when the error happened
07-18 21:06:31.952 12064-12426/com.archenians.inlesschat W/System.err: java.net.ConnectException: failed to connect to /192.168.49.220 (port 4446): connect failed: ECONNREFUSED (Connection refused)
07-18 21:06:31.955 12064-12426/com.archenians.inlesschat W/System.err: at libcore.io.IoBridge.connect(IoBridge.java:129)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:457)
at java.net.Socket.connect(Socket.java:927)
07-18 21:06:31.955 12064-12426/com.archenians.inlesschat W/System.err: at java.net.Socket.connect(Socket.java:853)
07-18 21:06:31.955 12064-12426/com.archenians.inlesschat W/System.err: at com.archenians.inlesschat.Asynctasks.SendMessageServer.doInBackground(SendMessageServer.java:53)
07-18 21:06:31.956 12064-12426/com.archenians.inlesschat W/System.err: at com.archenians.inlesschat.Asynctasks.SendMessageServer.doInBackground(SendMessageServer.java:22)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
07-18 21:06:31.956 12064-12426/com.archenians.inlesschat W/System.err: Caused by: android.system.ErrnoException: connect failed: ECONNREFUSED (Connection refused)
07-18 21:06:31.956 12064-12426/com.archenians.inlesschat W/System.err: at libcore.io.Posix.connect(Native Method)
07-18 21:06:31.957 12064-12426/com.archenians.inlesschat W/System.err: at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:111)
at libcore.io.IoBridge.connectErrno(IoBridge.java:144)
at libcore.io.IoBridge.connect(IoBridge.java:127)
... 11 more
07-18 21:06:31.957 12064-12426/com.archenians.inlesschat V/SendMessageServer: Send Message Server Error
07-18 21:06:31.974 12064-12177/com.archenians.inlesschat D/OpenGLRenderer: CacheTexture 3 upload: x, y, width height = 0, 28, 394, 382
It said the class SendMessageServer.java line 53
socket.connect(new InetSocketAddress(addr, serverPort));
It shows the same error on Client side.
EDIT :
Sending and Receive Message will be success if the Server and Client leave the Chat Room and create a new one. But, when it came success there is a new problem from the ServerThread.
There are my codes of ServerThread.java and ClientThread.java
ServerThread.java
public class ServerThread extends Thread {
private static final String TAG = "ServerThread";
private static final int SERVER_PORT = 4444;
public static ArrayList<InetAddress> clients;
private ServerSocket serverSocket;
public ServerThread(){
clients = new ArrayList<InetAddress>();
}
@Override
public void run() {
clients.clear();
try {
serverSocket = new ServerSocket(SERVER_PORT);
// Collect IP Client
while(true) {
Socket clientSocket = serverSocket.accept();
if(!clients.contains(clientSocket.getInetAddress())){
clients.add(clientSocket.getInetAddress());
Log.v(TAG, "New client: " + clientSocket.getInetAddress().getHostAddress());
}
clientSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void interrupt() {
super.interrupt();
try {
serverSocket.close();
Log.v(TAG, "Server init process interrupted");
} catch (IOException e) {
e.printStackTrace();
}
}
}
ClientThread.java
public class ClientThread extends Thread {
public static final String TAG = "ClientThread";
private static final int SERVER_PORT = 4444;
private InetAddress mServerAddr;
public ClientThread(InetAddress serverAddr){
mServerAddr = serverAddr;
}
@Override
public void run() {
Socket socket = new Socket();
try {
socket.bind(null);
socket.connect(new InetSocketAddress(mServerAddr, SERVER_PORT));
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
From the Server side, the error show on line :
serverSocket = new ServerSocket(SERVER_PORT);
This is the Bind Exception from Logcat
07-20 07:57:20.531 6417-6616/com.archenians.inlesschat W/System.err: java.net.BindException: bind failed: EADDRINUSE (Address already in use)
at libcore.io.IoBridge.bind(IoBridge.java:104)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:137)
07-20 07:57:20.532 6417-6616/com.archenians.inlesschat W/System.err: at java.net.ServerSocket.<init>(ServerSocket.java:106)
at java.net.ServerSocket.<init>(ServerSocket.java:75)
at com.archenians.inlesschat.Threads.ServerThread.run(ServerThread.java:28)
Caused by: android.system.ErrnoException: bind failed: EADDRINUSE (Address already in use)
at libcore.io.Posix.bind(Native Method)
07-20 07:57:20.533 6417-6616/com.archenians.inlesschat W/System.err: at libcore.io.ForwardingOs.bind(ForwardingOs.java:56)
at libcore.io.IoBridge.bind(IoBridge.java:102)
... 4 more
I have been try add a
setReuseAddress(true);
But the Sending Message will never success again even if the Server and Client close the Chat Room and create a new one again.
Can anybody helps me?
Show me where is my fault on these codes and how to fix it.