【问题标题】:Java Client-Server socket, reusing client socket throws "java.io.StreamCorruptedException: invalid type code: AC" [duplicate]Java客户端-服务器套接字,重用客户端套接字抛出“java.io.StreamCorruptedException:无效类型代码:AC”[重复]
【发布时间】:2014-12-06 14:07:08
【问题描述】:

这是我在 Stack Overflow 上的第一篇文章,所以我希望我能以最低限度的体面做这件事。

我尝试使用 Java 套接字实现一个简单的解决方案,但遇到了异常。我肯定在滥用 API,但我不知道为什么以及在哪里。

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

在服务器中,我创建了一个线程来做两件事:(1) 接受客户端请求,(2) 实例化一个新线程(运行 ClientWorker 实例)来处理客户端请求。

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

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

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

以下类是我创建的一个简单示例的一部分,只是为了显示此错误。

第一类是Message:

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

还有我用来测试这个的类: 包 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();
    }
}

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

非常感谢和亲切的问候。

【问题讨论】:

    标签: java multithreading sockets objectinputstream


    【解决方案1】:

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

    【讨论】:

    • 哇,就是这样!我尝试过类似版本的 ClientWorker,但我从未评论过“out.reset()”。非常感谢!
    猜你喜欢
    • 2015-04-07
    • 2012-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 2017-02-25
    • 2012-06-24
    相关资源
    最近更新 更多