Java套接字写对象stuck
我正在尝试创建一些本地聊天软件。 一切正常,但只坚持一点; 当用户点击一个按钮时,我的程序就卡住了 我编写了一个修改过的类,该类对服务器和客户端都起作用 下面是我的代码:Java套接字写对象stuck,java,sockets,Java,Sockets,我正在尝试创建一些本地聊天软件。 一切正常,但只坚持一点; 当用户点击一个按钮时,我的程序就卡住了 我编写了一个修改过的类,该类对服务器和客户端都起作用 下面是我的代码: package connections; import java.awt.event.ActionEvent; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import jav
package connections;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.channels.SocketChannel;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import ui.ChatWindow;
public class Chat{
private SocketChannel socketChannel;
private ConnectionType connectionType;
private ObjectOutputStream out;
private ObjectInputStream in;
private String strClientName;
private ChatWindow chatWindow;
private String strMessage;
public Chat(SocketChannel socketChannel, ConnectionType connectionType) {
this.socketChannel = socketChannel;
this.connectionType = connectionType;
init();
}
private void init() {
new Thread(this::initThread).start();
}
private void initThread() {
try {
out = new ObjectOutputStream(socketChannel.socket().getOutputStream());
in = new ObjectInputStream(socketChannel.socket().getInputStream());
if (connectionType == ConnectionType.SERVER) {
getClientName();
sendMyName();
} else {
sendMyName();
getClientName();
}
chatWindow = new ChatWindow();
chatWindow.btnSend.addActionListener(this::eventBtnSend);
chatWindow.setTitle(strClientName);
chatWindow.setSize(600, 400);
chatWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
if (connectionType == ConnectionType.CLIENT) {
chatWindow.setVisible(true);
chatWindow.requestFocus();
}
System.out.println("here");
beginChat();
System.out.println("thread ends");
} catch (IOException ex) {
Logger.getLogger(Chat.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void getClientName() {
try {
strClientName = (String) in.readObject();
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(Status.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void sendMyName() {
try {
out.writeObject(main.Config.myName);
out.flush();
} catch (IOException ex) {
Logger.getLogger(Status.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void beginChat() {
while (true) {
try {
waitForMessage();
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(Chat.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void waitForMessage() throws IOException, ClassNotFoundException {
System.out.println("waiting for Message : " + connectionType);
strMessage = (String) in.readObject();
System.out.println("Message received");
chatWindow.txtDisplay.append(strClientName + " : " + strMessage + "\n");
if(chatWindow.isVisible() == false){
chatWindow.setVisible(true);
}
}
private void sendMessage(String strMessage) {
try {
out.writeObject(strMessage);
out.flush();
} catch (IOException ex) {
Logger.getLogger(Chat.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void eventBtnSend(ActionEvent ae){
System.out.println("a");
sendMessage(chatWindow.txtMessage.getText());
System.out.println("b");
chatWindow.txtDisplay.append("Me : " + chatWindow.txtMessage.getText() + "\n");
System.out.println("c");
chatWindow.txtMessage.setText("");
}
}
当服务器和客户端连接时,我可以看到以下输出:
here
waiting for Message : SERVER
here
waiting for Message : CLIENT
但是当我点击发送按钮时,我的程序就卡住了。
单击按钮后,我可以看到:
a on console.
这个词是“积木”。它阻塞了I/O。它阻塞了
不要在事件线程上执行阻塞操作。所有网络代码都应该在单独的线程上运行。这包括readObject和writeObject、flush以及创建流。欢迎使用堆栈溢出。你的英语已经提高了,所以这个问题更容易理解。您可能希望简化程序,只关注出现错误的部分,而不是在问题中包含全部内容。有关这方面的信息,请参阅。这样你可以从更多的人那里得到更好的答案。如果你创建了一个服务器和客户机类而不是if/else,代码会更干净。如果你的程序卡住了,也许你应该使用JConsole检查程序中线程的状态我不知道为什么,但是,我更改了serversocketchannel by serversocket和socketchannel by socket,它解决了我的问题,怎么了?我在nio中遗漏了什么。请告诉我我真的很想知道原因是channels.socket返回的流似乎有未记录的内部同步,因此您不能同时读写。您将有一个线程在读取时阻塞,这将阻止写入执行。但是您只使用NIO来创建通道。从那里你可以使用流。那么,为什么不使用ServerSocket和Socket呢?这些流没有内部同步。