使用套接字和线程无法正常工作来发送和接收对象

时间:2014-11-18 21:34:58

标签: java multithreading sockets serialization objectinputstream

我目前正在创建一个服务,允许将对象从客户端发送到服务器,反之亦然,但遇到一个我遗憾无法解释和修复的问题。

首先,这里有一些有用的课程(我没有在这篇文章中列出所有方法,如getter和setter)。


/**
 * This launcher creates a NetworkInterface, waits for a connection, sends a message to the connected client and waits for an incoming message
 *
 */
public class ServerLauncher {

    public static void main(String[] args) {
        try {
            NetworkSystem n = new NetworkSystem(4096);
            n.startServerManager();

            while (n.getCommunications().isEmpty()) {
                // this line is unexpectedly magic
                System.out.println("Waiting for a new connection...");
            }

            do {
                n.getCommunications().get(0).send(new String("Hello, are you available?")); 
            } while (n.getCommunications().get(0).getReceiveManager().getReadObjects().isEmpty());

            System.out.println(n.getCommunications().get(0).getReceiveManager().getReadObjects().get(0));

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

/**
 * This launcher creates a NetworkSystem, connects to the server, waits for an incoming message and anwers back
 *
 */
public class ClientLauncher {

    public static void main(String[] args) {
        try {
            NetworkSystem n = new NetworkSystem(8192);
            n.instanciateCommunication(new Socket(InetAddress.getLocalHost(), 4096));

            while (n.getCommunications().get(0).getReceiveManager().getReadObjects().isEmpty()) {
                // this line is unexpectedly magic
                System.out.println("Waiting for an object...");
            }

            System.out.println(n.getCommunications().get(0).getReceiveManager().getReadObjects().get(0));
            n.getCommunications().get(0).getSendManager().send(new String("No, I am not! We will talk later..."));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

/**
 * This class handles every incoming messages.
 */
public class ReceiveManager implements Runnable {

    private ObjectInputStream inputStream;
    private CommunicationManager communicationManager;
    private List readObjects;
    private boolean receive;

    public ReceiveManager(CommunicationManager communicationManager) throws IOException {
        this.communicationManager = communicationManager;
        this.inputStream = new ObjectInputStream(this.communicationManager.getSocket().getInputStream());
        this.readObjects = new ArrayList();
        this.receive = true;
    }

    @Override
    public void run() {
        Object object = null;

        try {
            while ((object = this.inputStream.readObject()) != null && this.hasToReceive()) {
                this.readObjects.add(object);
            }
        } catch (ClassNotFoundException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            this.setContinueToReceive(false);
        }
    }

    private boolean hasToReceive() {
        return this.receive;
    }

    public void setContinueToReceive(boolean value) {
        this.receive = value;
    }
}

/**
 * This class allows the user to send messages
 */
public class SendManager {

    private ObjectOutputStream outputStream;
    private CommunicationManager communicationManager;

    public SendManager(CommunicationManager communicationManager) throws IOException {
        this.communicationManager = communicationManager;
        this.outputStream = new ObjectOutputStream(this.communicationManager.getSocket().getOutputStream());
    }

    public void send(Object object) throws IOException {
        this.outputStream.writeObject(object);
        this.outputStream.flush();
    }
}

所以基本上,正如你在ServerLauncher和ClientLauncher中注意到的那样,有两个"魔法"说明。当这两行被注释,我运行服务器然后客户端,没有任何反应。服务器和客户端只是运行而且永远不会停止。然而,当我取消注释这两条魔术线时,每一条都像魅力一样:消息被正确发送和接收。

你们知道这种意外行为的原因吗?

哦,是的,我忘了,如果你们要我上传一切来测试项目或其他什么,请告诉我: - )

1 个答案:

答案 0 :(得分:0)

您正在使用这些旋转循环使CPU匮乏。您应该在队列为空时睡觉或等待,或者更好的是阻止队列只有take()

注意您的循环条件不正确:

  1. readObject()在流的末尾没有返回null。它抛出EOFException
  2. 您还应该在调用hasToReceive()之前测试readObject() ,而不是之后。否则你总是多做一些阅读。