Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java套接字写对象stuck_Java_Sockets - Fatal编程技术网

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呢?这些流没有内部同步。