【问题标题】:Java sockets application with two listeners hanging挂起两个侦听器的 Java 套接字应用程序
【发布时间】:2018-11-28 14:43:41
【问题描述】:

我正在本地计算机上运行客户端和服务器,并尝试在两者之间发送文本消息。双方都可以读写。我正在使用ObjectInputStreamObjectOutputStream,因为我需要序列化对象。 Github repo

我的问题是,当我尝试从双方发送消息时,他们无法到达另一方并且听众挂起。

Host.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Host {
    private ServerSocket serverSocket;
    private Socket clientSocket;
    private ObjectOutputStream out;
    private ObjectInputStream in;
    private int portNumber = Settings.PORT;

    public Host() {
        acceptConnection();
        CommandListener commandListener = new CommandListener(in);
    }

    private void acceptConnection() {
        try {
            serverSocket = new ServerSocket(portNumber);
            clientSocket = serverSocket.accept();
            out = new ObjectOutputStream(clientSocket.getOutputStream());
            in = new ObjectInputStream(clientSocket.getInputStream());
        } catch (IOException e) {
            System.out.println("Exception caught when trying to listen on port "
                    + portNumber + " or listening for a connection");
            System.out.println(e.getMessage());
        }
    }

    public ObjectOutputStream getOut() {
        return out;
    }

    public ObjectInputStream getIn() {
        return in;
    }
}

Client.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
    private int portNumber = Settings.PORT;
    private ObjectOutputStream out;
    private ObjectInputStream in;
    private Socket clientSocket;

    public Client(String ip) {
        connectToHost(ip);
        CommandListener commandListener = new CommandListener(in);
    }

    public ObjectOutputStream getOut() {
        return out;
    }

    public ObjectInputStream getIn() {
        return in;
    }

    private void connectToHost(String ip) {
        try {
            clientSocket = new Socket(ip, portNumber);
            out = new ObjectOutputStream(clientSocket.getOutputStream());
            in = new ObjectInputStream(clientSocket.getInputStream());

        } catch (UnknownHostException e) {
            System.err.println("Don't know about host " + ip);
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to " + ip);
            e.printStackTrace();
        }
    }
}

CommandListener.java 类是一个线程,由客户端和服务器独立启动。

import java.io.IOException;
import java.io.ObjectInputStream;

public class CommandListener implements Runnable{
    private ObjectInputStream in;

    public CommandListener(ObjectInputStream in) {
        this.in = in;
        run();
    }

    public void run() {
        String inboundCmd;
        try {
            System.out.println("listener running, waiting for inbound command");
            inboundCmd = (String) in.readObject();
            System.out.println("listener read inbound command" + inboundCmd);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

打印出listener running, waiting for inbound command 后两者都挂起。 下面是我如何启动客户端和服务器:

RunHost.java

import java.io.IOException;
import java.io.ObjectOutputStream;

public class RunHost {
    public static void main(String[] args) throws IOException {
        Host host = new Host();
        ObjectOutputStream out = host.getOut();
        out.writeObject("host sending");
        out.flush();
    }
}

RunClient.java

import java.io.IOException;
import java.io.ObjectOutputStream;

public class RunClient {
    public static void main(String[] args) throws IOException {
        Client client = new Client("localhost");
        ObjectOutputStream out = client.getOut();
        out.writeObject("client sending");
        out.flush();
    }
}

知道如何解决这个问题吗?

【问题讨论】:

    标签: java sockets client-server objectinputstream objectoutputstream


    【解决方案1】:

    看起来主机和客户端都“挂”的原因仅仅是因为没有人在听对方之前写任何东西。

    您应该在RunClient.java 之前运行RunHost.java。从那里开始,您可以跟踪程序:

    1. 构造一个新主机(即运行RunHost.java
    2. 阻塞并等待客户端套接字连接
    3. 构造一个新的客户端(即运行RunClient.java
    4. ServerSocketClientSocket 的输入和输出流均已初始化
    5. ServerSocketClientSocket 都开始构建 CommandListener
    6. ServerSocketClientSocket 都开始监听输入

    看到问题了吗?主要问题是因为您在 CommandListener 构造函数中调用了方法 run(),因此服务器端和客户端都开始阻止侦听,而没有任何人发送任何内容。

    一个快速的解决方法是从CommandListener 构造函数中取出run() 调用,然后在准备好时单独调用它。

    例如:

    CommandListener.java中的构造函数改为:

    public CommandListener(ObjectInputStream in) {
        this.in = in;
    }
    

    添加一种在Client.java 中为客户端获取CommandListener 的方法(请注意,这意味着您应该通过在Client 构造函数中执行cl = new CommandListener(in); 来存储CommandListener):

    public CommandListener getCL() {
        return cl;
    }
    

    RunClient.java 更改为:

    public static void main(String[] args) throws IOException {
        Client client = new Client("localhost");
        ObjectOutputStream out = client.getOut();
        out.writeObject("client sending");
        out.flush();
        CommandListener cl = client.getCL();
        cl.run();
    }
    

    最后,在Host 的构造函数中调用CommandListenerrun() 方法:

    public Host() {
        acceptConnection();
        CommandListener commandListener = new CommandListener(in);
        commandListener.run();
    }
    

    它应该按预期工作。

    但老实说,鉴于CommandListener 造成的混乱,您可能首先要重新考虑开设该课程。我的意思是,这里似乎没有必要,所以......

    P/S 如果有任何不清楚的地方,请随时告诉我/它仍然不起作用

    【讨论】:

    • 感谢您的回答,我采纳了您的建议,但我仍然遇到同样的问题。一开始我不明白你上这门课是什么意思?
    • 这是完整代码:Host.java:pastebin.com/hyT8HWTfClient.java:pastebin.com/0mPu7H0wComamndListener.java:pastebin.com/a3nGarXkRunClient.java:pastebin.com/b6Ly75xR@98765432@wa@:@98765432@wa不变)在RunClient.java之前运行RunHost.java
    • 另外,我只是说,由于CommandListener 并没有真正做太多(此时),您可能希望完全删除它:P
    • 成功了。交换了命令。但是,我不能交换多个字符串。我发现我的代码有两个问题: 1. 我没有一个持续监听的 while 循环。 2. 监听器没有在线程中运行。明天将发布更新的代码。无论如何,感谢您的支持。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    相关资源
    最近更新 更多