gpt4 book ai didi

具有两个挂起监听器的 Java 套接字应用程序

转载 作者:行者123 更新时间:2023-12-02 11:06:19 25 4
gpt4 key购买 nike

我正在本地计算机上运行客户端和服务器,并尝试在两者之间发送文本消息。双方都可以读写。我正在使用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 class是一个线程,由客户端和服务器端独立启动。

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

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

最佳答案

主机和客户端看起来都“挂起”的原因很简单,因为在听对方说话之前没有人能够写任何东西。

您应该在 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 的方法(请注意,这意味着您应该通过执行以下操作来存储 CommandListener cl = new CommandListener(in);Client 构造函数中):

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 如果有任何不清楚的地方请随时告诉我/它仍然不起作用

关于具有两个挂起监听器的 Java 套接字应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50931728/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com