我正在本地计算机上运行客户端和服务器,并试图在两者之间发送文本消息。双方都可以读写。我使用ObjectInputStream
和ObjectOutputStream
是因为我需要序列化对象。 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();
}
}
有什么解决方法吗?
答案 0 :(得分:1)
主机和客户端似乎都“挂起”的原因仅仅是因为没有人在听另一方之前就设法写了任何东西。
您应该在RunHost.java
之前运行RunClient.java
。从那里开始,您可以跟踪程序:
RunHost.java
已运行)RunClient.java
已运行)ServerSocket
和ClientSocket
的输入和输出流均已初始化ServerSocket
和ClientSocket
都开始构建CommandListener
ServerSocket
和ClientSocket
都开始监听输入看到问题了吗?主要问题是因为您在run()
构造函数中调用了方法CommandListener
,所以服务器端和客户端都开始阻塞监听,而没有任何人发送任何东西。
一种快速解决方案是从run()
构造函数中取出CommandListener
调用,然后在准备好它时分别调用它。
例如:
将CommandListener.java
中的构造函数更改为:
public CommandListener(ObjectInputStream in) {
this.in = in;
}
添加一种在CommandListener
中为客户端获取Client.java
的方法(请注意,这意味着您应通过在{{1}中执行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();
}
的构造函数中调用CommandListener
的{{1}}方法:
run()
它应该按预期工作。
但是,老实说,考虑到Host
造成的混乱,您可能首先要重新考虑使用该类。我的意思是,在这里似乎没有必要,所以...
P / S随时让我知道是否有任何不清楚的地方/仍然无法解决问题