Java客户端 - 服务器套接字,重用客户端套接字抛出“java.io.StreamCorruptedException:无效的类型代码:AC”

时间:2014-12-06 14:07:08

标签: java multithreading sockets objectinputstream

这是我在Stack Overflow上的第一篇文章,所以我希望我能以最低限度的方式做到这一点。

我尝试使用Java套接字实现一个简单的解决方案,但我有一个例外。我肯定会滥用API,但我无法弄清楚原因和地点。

客户端需要向服务器发送多个二进制消息,并且它(客户端)必须重用相同的套接字。

在服务器中,我创建了一个执行两项操作的线程:(1)接受客户端请求;(2)实例化新线程(运行ClientWorker实例)以处理客户端请求。

如果我只是从客户端发送一条消息,一切正常。然而,当我尝试发送多条消息时,在第二条消息中我有以下异常:

  

java.io.StreamCorruptedException:无效的类型代码:AC at   java.io.ObjectInputStream.readObject0(未知来源)at   java.io.ObjectInputStream.readObject(未知来源)at   simple.socketexample.ClientWorker.run(ClientWorker.java:26)at   java.lang.Thread.run(未知来源)

异常发生在我的ClienWorker类中,在“Message message =(Message)in.readObject();”行中。请注意,服务器始终会成功接收第一条消息。

以下类是我为创建此错误而创建的简单示例的一部分。

第一堂课是讯息:

package simple.socketexample;

import java.io.Serializable;

public class Message implements Serializable {
    private static final long serialVersionUID = 4473470814745876900L;
    private String text;
    private int number;

    public Message(String text, int number) {
        super();
        this.text = text;
        this.number = number;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    @Override
    public String toString() {
        return "Message [text=" + text + ", number=" + number + "]";
    }
}

这是我的客户:

public class Client {
    private final int SERVER_PORT = 3456;
    private final String SERVER_HOST = "localhost";
    private Socket serverSocket;

    public void connect() throws IOException, UnknownHostException {
        serverSocket = new Socket(SERVER_HOST, SERVER_PORT);
    }

    public void disconnect() throws IOException {
        serverSocket.close();
    }

    public void sendMessage(Message message) throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(serverSocket.getOutputStream());
        out.writeObject(message);
        out.flush();
        out.reset();
    }
}

服务器:

public class Server {
    private final int SERVER_PORT = 3456;

    public void start() throws IOException {
        Thread acceptConnectionsThread = new Thread(new Runnable() {
            public void run() {
                // Instantiates the socket
                ServerSocket serverSocket = null;
                try {
                    serverSocket = new ServerSocket(SERVER_PORT);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                // Starts accepting client connections
                while(true) {
                    Socket socketFromClient = null;
                    try {
                        socketFromClient = serverSocket.accept();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    // Create a new "client dedicated thread"
                    ClientWorker clientWorker = new ClientWorker(socketFromClient);
                    Thread clientDedicatedThread = new Thread(clientWorker);
                    clientDedicatedThread.start();
                }
            }
        });

        acceptConnectionsThread.start();

    }
}

我的客户工作人员:

public class ClientWorker implements Runnable {
    private Socket socketFromClient;

    public ClientWorker(Socket socketFromClient) {
        super();
        this.socketFromClient = socketFromClient;
    }

    public void run() {
        ObjectInputStream in = null;
        try {
            in = new ObjectInputStream(socketFromClient.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }

        while(true) {
            try {
                Message message  = (Message)in.readObject();
                System.out.println(message);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                break;
            } catch (IOException e) {
                e.printStackTrace();
                break;
            }
        }
    }
}

我用过的课程测试了这个:     package simple.socketexample;

import java.io.IOException;

/**
 * Hello world!
 *
 */
public class App {
    public static void main(String[] args) throws Exception {
        // Start the server in a new (background) thread
        Thread serverInBackground = new Thread(new Runnable() {
            public void run() {
                Server server = new Server();
                try {
                    server.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        serverInBackground.start();

        // Client and connect a client
        Client client = new Client();
        client.connect();

        // Sending one message to the server
        client.sendMessage(new Message("MessageOne", 1));

        // Sending another message to the server
        client.sendMessage(new Message("MessageTwo", 2));

        // Closing the client
        client.disconnect();
    }
}

问题可能只是一个小细节,解决方案可能也在我的眼前,但不知怎的,我看不到它。有没有人遇到过类似的问题?你是怎么解决的?

非常感谢和亲切的问候。

1 个答案:

答案 0 :(得分:2)

试试这个ClientWorker

public class ClientWorker implements Runnable {
    private Socket socketFromClient;

    public ClientWorker(Socket socketFromClient) {
        super();
        this.socketFromClient = socketFromClient;
    }

    public void run() {

        while(true) {
            ObjectInputStream in = null;
            try {
                in = new ObjectInputStream(socketFromClient.getInputStream());
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
            try {
                    Message message  = (Message)in.readObject();
                    System.out.println(message);

            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                break;
            } catch (IOException e) {
                e.printStackTrace();
                break;
            }
        }
    }
}

并在客户端

中注释reset()
    public void sendMessage(Message message) throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(serverSocket.getOutputStream());
        out.writeObject(message);
        out.flush();
//        out.reset();
    }