我有java.lang.ClassCastException,但我发送的是Object,而不是String

时间:2013-06-04 07:49:24

标签: java string sockets serialization serversocket

我通过套接字发送序列化对象。问题是当我只发送一个字符串(消息)时,我在标题上提到了这个错误。所以这里是创建套接字对象的类:

package Pinger;

import java.io.*;
import java.util.Vector;

public class ChatMessage implements Serializable {

protected static final long serialVersionUID = 1112122200L;

static final int WHOISIN = 0, MESSAGE = 1, LOGOUT = 2, JOB = 3;
private int type,frequency,maxScans,NUMTHREADS,ttl;
Vector <String> IPS;
private String message;

// constructor
ChatMessage(int type, String message) {
    this.type = type;
    this.message = message;
}
ChatMessage (int type, int frequency, Vector <String> IPS, int maxScans, int NUMTHREADS, int ttl){
    this.type=type;
    this.frequency=frequency;
    this.IPS=IPS;
    this.maxScans=maxScans;
    this.NUMTHREADS=NUMTHREADS;
    this.ttl=ttl;
}

// getters
    .
    .
    .

     }

此类创建可通过套接字发送的可序列化对象。问题是当我发送字符串消息(该字符串传递给ChatMessage类)时,我收到了java无法从String转换为ChatMessage的错误。另外,我将为您提供Client和ClientGUI类,为您提供理解我的代码所需的一切。我真的不知道错误在哪里。你能帮助我吗?最好的问候。

package Pinger;

import java.net.*;
import java.io.*;
import java.util.*;
public class Client  {

// for I/O
private ObjectInputStream sInput;       // to read from the socket
private ObjectOutputStream sOutput;     // to write on the socket
private Socket socket;

// if I use a GUI or not
private ClientGUI cg;

// the server, the port and the username
private String server, username;
private int port;

/*
 *  Constructor called by console mode
 *  server: the server address
 *  port: the port number
 *  username: the username
 */
Client(String server, int port, String username) {
    // which calls the common constructor with the GUI set to null
    this(server, port, username, null);
}

/*
 * Constructor call when used from a GUI
 * in console mode the ClienGUI parameter is null
 */
Client(String server, int port, String username, ClientGUI cg) {
    this.server = server;
    this.port = port;
    this.username = username;
    // save if we are in GUI mode or not
    this.cg = cg;
}

/*
 * To start the dialog
 */
public boolean start() {
    // try to connect to the server
    try {
        socket = new Socket(server, port);
    } 
    // if it failed not much I can so
    catch(Exception ec) {
        display("Error connecting to server:" + ec);
        return false;
    }

    String msg = "Connection accepted " + socket.getInetAddress() + ":" + socket.getPort();
    display(msg);

    /* Creating both Data Stream */
    try
    {
        sInput  = new ObjectInputStream(socket.getInputStream());
        sOutput = new ObjectOutputStream(socket.getOutputStream());
    }
    catch (IOException eIO) {
        display("Exception creating new Input/output Streams: " + eIO);
        return false;
    } 
    new ListenFromServer().start();
    try
    {
        sOutput.writeObject(username);
    }
    catch (IOException eIO) {
        display("Exception doing login : " + eIO);
        disconnect();
        return false;
    }
    // success we inform the caller that it worked
    return true;
}

/*
 * To send a message to the console or the GUI
 */
private void display(String msg) {
    if(cg == null)
        System.out.println(msg);      // println in console mode
    else
        cg.append(msg + "\n");      // append to the ClientGUI JTextArea (or whatever)
}

/*
 * To send a message to the server
 */
void sendMessage(ChatMessage msg) {
    try {
        System.out.println(msg);
        sOutput.writeObject(msg);
    }
    catch(IOException e) {
        display("Exception writing to server: " + e);
    }
}

/*
 * When something goes wrong
 * Close the Input/Output streams and disconnect not much to do in the catch clause
 */
private void disconnect() {
    try { 
        if(sInput != null) sInput.close();
    }
    catch(Exception e) {} // not much else I can do
    try {
        if(sOutput != null) sOutput.close();
    }
    catch(Exception e) {} // not much else I can do
    try{
        if(socket != null) socket.close();
    }
    catch(Exception e) {} // not much else I can do

    // inform the GUI
    if(cg != null)
        cg.connectionFailed();

}
class ListenFromServer extends Thread {

    public void run() {
        while(true) {
            try {
                ChatMessage msg = (ChatMessage) sInput.readObject();
                //if (nesto instanceof String)
                //msg = (String) sInput.readObject();
                //}
                // if console mode print the message and add back the prompt
                if(cg == null) {
                    System.out.println(msg.getMessage());
                    System.out.print("> ");
                }
                else {
                    cg.append(msg.getMessage());
                }
            }
            catch(IOException e) {
                display("Server has close the connection: " + e);
                if(cg != null) 
                    cg.connectionFailed();
                break;
            }
            // can't happen with a String object but need the catch anyhow
            catch(ClassNotFoundException e2) {
            }
        }
    }
}
}

此处还有类客户端的GUI类:

package Pinger;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.InetAddress;
import java.net.UnknownHostException;


/*
 * The Client with its GUI
 */
public class ClientGUI extends JFrame implements ActionListener {

private static final long serialVersionUID = 1L;
// will first hold "Username:", later on "Enter message"
private JLabel label;
// to hold the Username and later on the messages
private JTextField tf;
// to hold the server address an the port number
private JTextField tfServer, tfPort;
// to Logout and get the list of the users
private JButton login, logout, whoIsIn;
// for the chat room
private JTextArea ta;
// if it is for connection
private boolean connected;
// the Client object
private Client client;
// the default port number
private int defaultPort;
private String defaultHost;
InetAddress ComputerIP;

// Constructor connection receiving a socket number
ClientGUI(String host, int port) throws UnknownHostException {

    super("Chat Client");
    defaultPort = port;
    defaultHost = host;

    // The NorthPanel with:
    JPanel northPanel = new JPanel(new GridLayout(3,1));
    // the server name anmd the port number
    JPanel serverAndPort = new JPanel(new GridLayout(1,5, 1, 3));
    // the two JTextField with default value for server address and port number
    tfServer = new JTextField(host);
    tfPort = new JTextField("" + port);
    tfPort.setHorizontalAlignment(SwingConstants.RIGHT);

    serverAndPort.add(new JLabel("Server Address:  "));
    serverAndPort.add(tfServer);
    serverAndPort.add(new JLabel("Port Number:  "));
    serverAndPort.add(tfPort);
    serverAndPort.add(new JLabel(""));
    // adds the Server an port field to the GUI
    northPanel.add(serverAndPort);

    // the Label and the TextField
    ComputerIP = InetAddress.getLocalHost();
    label = new JLabel("Enter your username below", SwingConstants.CENTER);
    northPanel.add(label);
    tf = new JTextField(ComputerIP.toString());
    tf.setBackground(Color.WHITE);
    northPanel.add(tf);
    add(northPanel, BorderLayout.NORTH);

    // The CenterPanel which is the chat room
    ta = new JTextArea("Clients logs\n", 80, 80);
    JPanel centerPanel = new JPanel(new GridLayout(1,1));
    centerPanel.add(new JScrollPane(ta));
    ta.setEditable(false);
    add(centerPanel, BorderLayout.CENTER);

    // the 3 buttons
    login = new JButton("Login");
    login.addActionListener(this);
    logout = new JButton("Logout");
    logout.addActionListener(this);
    logout.setEnabled(false);       // you have to login before being able to logout
    whoIsIn = new JButton("Who is in");
    whoIsIn.addActionListener(this);
    whoIsIn.setEnabled(false);      // you have to login before being able to Who is in

    JPanel southPanel = new JPanel();
    southPanel.add(login);
    southPanel.add(logout);
    southPanel.add(whoIsIn);
    add(southPanel, BorderLayout.SOUTH);

    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(600, 600);
    setVisible(true);
    tf.requestFocus();

}

// called by the Client to append text in the TextArea 
void append(String str) {
    ta.append(str);
    ta.setCaretPosition(ta.getText().length() - 1);
}
// called by the GUI is the connection failed
// we reset our buttons, label, textfield
void connectionFailed() {
    login.setEnabled(true);
    logout.setEnabled(false);
    whoIsIn.setEnabled(false);
    InetAddress localIP = null;
    label.setText("Enter your username below");
    try {
        localIP=InetAddress.getLocalHost();
    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    tf.setText(localIP.getHostAddress().toString());
    // reset port number and host name as a construction time
    tfPort.setText("" + defaultPort);
    tfServer.setText(defaultHost);
    // let the user change them
    tfServer.setEditable(false);
    tfPort.setEditable(false);
    // don't react to a <CR> after the username
    tf.removeActionListener(this);
    connected = false;
}

/*
* Button or JTextField clicked
*/
public void actionPerformed(ActionEvent e) {
    Object o = e.getSource();
    // if it is the Logout button
    if(o == logout) {
        client.sendMessage(new ChatMessage(ChatMessage.LOGOUT, ""));
        return;
    }
    // if it the who is in button
    if(o == whoIsIn) {
        client.sendMessage(new ChatMessage(ChatMessage.WHOISIN, ""));               
        return;
    }

    // ok it is coming from the JTextField
    if(connected) {
        // just have to send the message
        client.sendMessage(new ChatMessage(ChatMessage.MESSAGE, tf.getText()));             
        tf.setText("");
        return;
    }


    if(o == login) {
        // ok it is a connection request
        String username = tf.getText().trim();
        // empty username ignore it
        if(username.length() == 0)
            return;
        // empty serverAddress ignore it
        String server = tfServer.getText().trim();
        if(server.length() == 0)
            return;
        // empty or invalid port numer, ignore it
        String portNumber = tfPort.getText().trim();
        if(portNumber.length() == 0)
            return;
        int port = 0;
        try {
            port = Integer.parseInt(portNumber);
        }
        catch(Exception en) {
            return;   // nothing I can do if port number is not valid
        }

        // try creating a new Client with GUI
        client = new Client(server, port, username, this);
        // test if we can start the Client
        if(!client.start()) 
            return;
        tf.setText("");
        label.setText("Enter your message below");
        connected = true;

        // disable login button
        login.setEnabled(false);
        // enable the 2 buttons
        logout.setEnabled(true);
        whoIsIn.setEnabled(true);
        // disable the Server and Port JTextField
        tfServer.setEditable(false);
        tfPort.setEditable(false);
        // Action listener for when the user enter a message
        tf.addActionListener(this);
    }

}

// to start the whole thing the server
public static void main(String[] args) throws UnknownHostException {
    new ClientGUI("localhost", 6000);
}

}

编辑1:增加了预期堆栈跟踪

Exception in thread "Thread-2" java.lang.ClassCastException: java.lang.String cannot be 
cast to Pinger.ChatMessage
    at Pinger.Client$ListenFromServer.run(Client.java:143)

2 个答案:

答案 0 :(得分:1)

这个怎么样:

sOutput.writeObject(username);

您发送到服务器的第一件事是String,而在服务器端,您假设您是ChatMessage

答案 1 :(得分:0)

很抱歉打扰你的人。问题在于我没有在这里展示的服务器类(我的坏)。我通过socket发送了对ChatMessage对象的String insted。这就是我收到错误的原因。我之前没有注意到......抱歉花时间。问题出在Server类中,它向所有客户端广播消息。 ObjectInputStream被转换为ChatMessage()的String insted。再一次抱歉打扰你...真的是我的坏......