Question

Based on this tutorial and another tutorial that unfortunately I can't get my hands on right now, I've created my Client-Server application but instead of sending string messages, the client asks for data(using Object Input/Output Streams) from the server using a custom class "Message".
First I created, the basic concept of it, using simple Java and tested both the server and the client on my computer, and displayed the data my client received in the console output. Everything worked out great, so I started to make the transition to Android(for the client). Trying to use the AsycTask, as show in the linked tutorial, I've managed so far to establish the connection between the client and the server. But I'm having a problem getting my server to read my "Message" object. Here are my classes:

Server:

import java.io.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class T_Server extends Thread {

    private static int port = 4444;
    private ServerSocket srvSock = null;
    private Socket clntSock = null;
    private boolean running = false;
    private ObjectInputStream in;
    private ObjectOutputStream out;
    private OnMessageReceived msgListener;
    private Message msgIn;
    private Object objSend;


    public static void main(String[] args) {
        OnMessageReceived _msgListener=new OnMessageReceived();
        T_Server server=new T_Server(_msgListener);

        server.start();
    }


    public T_Server(OnMessageReceived _msgListener) {
        this.msgListener = _msgListener;
    }

    public void send(Object _msg) {
        if (out != null) {
            try {
                out.writeObject(_msg);
                out.flush();
            } catch (IOException ex) {
                Logger.getLogger(T_Server.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    @Override
    public void run() {

        running = true;

        try {
            srvSock = new ServerSocket(port);
            System.out.println("Server startet. IP : " + InetAddress.getLocalHost() + ", Port : " + srvSock.getLocalPort());
            System.out.println("\nWaiting for a client ...");
            clntSock = srvSock.accept();
            System.out.println("\nClient accepted: " + clntSock);

            try {
                out = new ObjectOutputStream(clntSock.getOutputStream());
                in = new ObjectInputStream(clntSock.getInputStream());

                while (running) {
                    msgIn = (Message) in.readObject();
                    System.out.println(msgIn.toString());

                    objSend = msgListener.messageReceived(msgIn);
                    send(objSend);
                }
            } catch (Exception e) {
                System.out.println("S: Error");
                e.printStackTrace();
            } finally {
                clntSock.close();
            }

        } catch (Exception e) {
            System.out.println("S: Error");
            e.printStackTrace();
        }

    }
}

I use the same Message class both on the Server and on the Client Message Class:

import java.io.Serializable;

public class Message implements Serializable{

    private static final long serialVersionUID = 1L;
    public String sender, content, type;

    public Message(String sender, String type, String content){
         this.sender = sender; this.type=type; this.content = content;
    }

    @Override
    public String toString(){
        return "{type='"+type+"', sender='"+sender+"', content='"+content+"'}";
    }

}

I have also created a class to handle the Messages, on the server side, called OnMessageReceived.
P.S. In this class there are fields and some options that have to do with my backend database.
OnMessageReceived:

import java.sql.SQLException;
import java.util.regex.Pattern;

public class OnMessageReceived {

    public Object messageReceived(Message message) throws SQLException {
        Message _msg = message;
        Database db = new Database();
        Object objReturn;
        String strResult;
        boolean addResult;
        final Pattern pattern = Pattern.compile("\\[.*?&");
        final String[] result;
        if (_msg.type.equals("getUsers")) {
            objReturn = db.getUsers();
            return objReturn;
        } else if (_msg.type.equals("getFriends")) {
            objReturn = db.getFriends(_msg.sender);
            return objReturn;
        } else if (_msg.type.equals("addFriend")) {
            String _UserName, _UserNameFriend;
            _UserName = _msg.sender;
            _UserNameFriend = _msg.content;
            addResult = db.addFriend(_UserName, _UserNameFriend);
            if (addResult) {
                strResult = "Add was successfull";
                return strResult;
            } else if (!addResult) {
                strResult = "Add failed";
                return strResult;
            }
            System.out.println(addResult);
        } else if (_msg.type.equals("addUser")) {
            String _UserName, _Password, _Phone;
            result = pattern.split(_msg.content);
            _UserName = _msg.sender;
            _Password = result[0];
            _Phone = result[1];
            addResult = db.addUser(_UserName, _Password, _Phone);
            if (addResult) {
                strResult = "Add was successfull";
                return strResult;
            } else if (!addResult) {
                strResult = "Add failed";
                return strResult;
            }
            System.out.println(addResult);
        } else if (_msg.type.equals("Login")) {
            boolean isUser;
            String _UserName;
            _UserName = _msg.sender;
            isUser = db.isUser(_UserName);
            if (isUser) {
                strResult = "Login Successfull";
                return strResult;
            } else if (!isUser) {
                strResult = "Login failed";
                return strResult;
            }
        }
        return null;
    }
}

For the client side(on the Android) it's very simillar to the one in the linked tutorial. The difference is that I only have 2 buttons, one to connect to the server and one to send my message, which is an instance of my Message class.
Client:

import java.io.*;
import java.net.*;
import android.util.Log;


public class T_Client  {
    private static final String TAG = "MyActivity";

    private static String serverIP = "192.168.1.11";
    private static int port = 4444;
    private InetAddress serverAddr = null;
    private Socket sock = null;
    private boolean running = false;
    private ObjectInputStream in;
    private ObjectOutputStream out;
    private OnMessageReceived msgListener;
    Object objIn, objReceived;

    public T_Client(OnMessageReceived _msgListener){
        this.msgListener=_msgListener;
    }

    public void send(Message _msg) {
        if (out != null) {
            try {
                out.writeObject(_msg);
                out.flush();
                Log.i(TAG,"Outgoing : " + _msg.toString());
            } catch (IOException ex) {
                Log.e(TAG,ex.toString());
            }
        }
    }

    public void stopClient(){
        running = false;
    }

    public void run(){
        running = true;
        try {
            //here you must put your computer's IP address.
            serverAddr = InetAddress.getByName(serverIP);

            Log.i("TCP Client", "C: Connecting...");

            //create a socket to make the connection with the server
            sock = new Socket(serverAddr, port);

            try {

                //send the message to the server
                out =new ObjectOutputStream(sock.getOutputStream());               

                //receive the message which the server sends back
                in =new ObjectInputStream(sock.getInputStream());

                Log.i("TCP Client", "C: Connected.");

                //in this while the client listens for the messages sent by the server
                while (running) {
                    objIn = in.readObject();

                    if (objIn != null && msgListener != null) {
                        //call the method messageReceived from MyActivity class
                        msgListener.messageReceived(objIn);
                    }
                    objIn = null;

                }


                Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + objIn + "'");


            } 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.
                sock.close();
            }

        } catch (Exception e) {

            Log.e("TCP", "C: Error", e);

        }

    }

    public interface OnMessageReceived {
        public void messageReceived(Object objReceived);
    }

}

Main Activity:

import java.io.IOException;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity {
    private static final String TAG = "MyActivity";

    private T_Client client;
    private Message msgSend;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    public void connect(View v) throws IOException {        
        new connectTask().execute("");

    }

    public void btnSend(View v) throws IOException {
        msgSend=new Message("Setlios", "getUsers", "");
        if(client!=null){
            client.send(msgSend);
        }

    }


    public class connectTask extends AsyncTask<Object,Object,T_Client> {

        @Override
        protected T_Client doInBackground(Object... objIn) {

            //we create a TCPClient object and
            client = new T_Client(new T_Client.OnMessageReceived() {
                @Override
                //here the messageReceived method is implemented
                public void messageReceived(Object objIn) {
                    //this method calls the onProgressUpdate
                    publishProgress(objIn);
                }
            });
            client.run();

            return null;
        }

        @Override
        protected void onProgressUpdate(Object... values) {
            super.onProgressUpdate(values);

            Log.i(TAG,values.getClass().getName().toString());
        }
    }

}

When I hit the "Send" button I get this error on the server console which points me to the point where I read the object read from the ObjectInputStream and pass it an instance of the Message class but I can't understand what the problem is. I also noticed that it shows this "in.neverhide.connect" which is the package name of the project for my android client

java.lang.ClassNotFoundException: in.neverhide.connect.Message
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:622)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1593)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
    at Objects_WORKING.T_Server.run(T_Server.java:61)
Was it helpful?

Solution

Ok after searching around I found this post and the answer from Akinsola 'mys Tunmise. I've made the Message class into a jar and used it as an external reference in both the client and the server.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top