【问题标题】:Sending and receiving objects using sockets and threads not working properly使用套接字和线程无法正常工作的发送和接收对象
【发布时间】:2014-11-18 21:34:58
【问题描述】:

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

首先,这里是有用的类(我没有把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 中注意到的那样,有两个“神奇”指令。当这两行被注释并且我运行服务器然后客户端时,没有任何反应。服务器和客户端只是在运行并且永不停止。然而,当我取消注释这两条神奇的线时,每条线都像一个魅力:消息被正确发送和接收。

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

哦,是的,我忘了,如果你们想让我上传所有东西来测试项目或其他什么,请告诉我 :-)

【问题讨论】:

    标签: java multithreading sockets serialization objectinputstream


    【解决方案1】:

    这些自旋循环使 CPU 处于饥饿状态。您应该在队列为空时休眠或等待,或者最好只是 take()from 阻塞队列。

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

    1. readObject() 不会在流结束时返回 null。它抛出EOFException
    2. 您还应该在调用readObject() 而不是之后测试hasToReceive() 之前。否则,您总是需要额外阅读。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-13
      • 2010-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-13
      相关资源
      最近更新 更多