从ObjectInputStream读取时服务器上的ClassNotFoundException

时间:2013-10-08 16:36:56

标签: java android android-asynctask objectinputstream

基于this教程和另一个教程,遗憾的是我现在无法开始,我已经创建了我的客户端 - 服务器应用程序,但客户端要求数据而不是发送字符串消息(使用对象输入/使用自定义类“Message”从服务器输出Streams 首先,我创建了它的基本概念,使用简单的Java并在我的计算机上测试服务器和客户端,并显示客户端在控制台输出中收到的数据。一切都很好,所以我开始转向Android(为客户端)。尝试使用AsycTask,如链接教程中所示,我已经管理到目前为止建立客户端和服务器之间的连接。但我在让我的服务器读取我的“消息”对象时遇到问题。这是我的课程:

服务器

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

    }
}

我在服务器和客户端上都使用相同的Message类 消息类:

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+"'}";
    }

}

我还创建了一个类来处理服务器端的消息,称为OnMessageReceived 附:在这个类中,有一些字段和一些与我的后端数据库有关的选项 的 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;
    }
}

对于客户端(在Android上),它与链接教程中的那个非常相似。 不同之处在于我只有2个按钮,一个用于连接服务器,另一个用于发送消息,这是我的Message类的一个实例。
客户端:

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);
    }

}

主要活动:

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

}

当我点击“发送”按钮时,我在服务器控制台上收到此错误,这指向我读取从ObjectInputStream读取的对象并向其传递Message类的实例,但我无法理解是什么问题是。我还注意到它显示了这个“in.neverhide.connect”,它是我的android客户端项目的包名称

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)

1 个答案:

答案 0 :(得分:0)

好的搜索后我发现this帖子和Akinsola'mys Tunmise的回答。我已将Message类放入jar中,并在客户端和服务器中将其用作外部引用。