0

私はJavaソケットを学んでいるので、クライアントとサーバーの2つのフレームで機能的で非常に単純なチャットを作成しました。アプリはローカルのみで動作します。しかし、ウィンドウを閉じても停止しません (両方のフレーム クラスに WindowListener を追加しましたが): 何が問題なのですか?

最初にサーバーを実行し、次にクライアントを実行することを忘れないでください。両方のフレームは、クライアント接続後にのみ表示されます。

SimpleSocketFrame.java (両方のフレームの基本クラス) は次のとおりです。

package com.loloof64.java_se.simple_socket;

import java.awt.GridLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public abstract class SimpleSocketFrame extends JFrame {

    public SimpleSocketFrame() {
        setTitle(getFrameTitle());
        setLayout(new GridLayout(0, 1));

         messageToAddField = new JTextField(30);
     messageToAddField.addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER){
                    if ( ! messageToAddField.getText().isEmpty()) {
                        addMessage(messageToAddField.getText());
                        messageToAddField.setText("");
                    }
                }
            }

    });

        printedMessagesArea = new JTextArea(10,30);
        printedMessagesArea.setEditable(false);

        add(messageToAddField);
        add(printedMessagesArea);

    pack();
}

protected abstract void addMessage(String s);
protected abstract String getFrameTitle();

private static final long serialVersionUID = -5861605385948623162L;
protected JTextArea printedMessagesArea;
private JTextField messageToAddField;

}

これがサーバーアプリクラスです: SimpleSocketServer.java

package com.loloof64.java_se.simple_socket;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JOptionPane;

public class SimpleSocketServer extends SimpleSocketFrame {

    public SimpleSocketServer(){
        super();
        setTitle("Simple Server");
        try {
            serverSocket = new ServerSocket(12345);
            relatedSocket = serverSocket.accept();

            outStream = new PrintStream(relatedSocket.getOutputStream());
            isr = new InputStreamReader(relatedSocket.getInputStream());
            inStream = new BufferedReader(isr);

            final InStreamRunnable inStreamRunnable = new InStreamRunnable();
            Thread inStreamReaderThread = new Thread(inStreamRunnable);



            addWindowListener(new WindowAdapter() {

                @Override
                public void windowClosing(WindowEvent evt) {
                    try {
                        inStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                    outStream.close();
                try {
                    relatedSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                    inStreamRunnable.stop();
                    System.exit(0);
                }

            });

            inStreamReaderThread.start();
        } catch (IOException e) {
            JOptionPane.showMessageDialog(this, "Could not create the server !!!",
                    "Fatal error", JOptionPane.ERROR_MESSAGE);
            System.exit(1);
            e.printStackTrace();
        }
    }

    private class InStreamRunnable implements Runnable {

        @Override
        public void run() {
            while (weMustGoOn){
                String line;
                try {
                    line = inStream.readLine();
                                   printedMessagesArea.setText(printedMessagesArea.getText()+line+"\n");
                } catch (IOException e) {

                }
            }
    }

        public void stop(){
            weMustGoOn = false;
        }

        private boolean weMustGoOn = true;

    }

    @Override
    protected void addMessage(String s) {
        s = "Serveur> "+s;
        outStream.println(s);
        printedMessagesArea.setText(printedMessagesArea.getText()+"Client> "+s+"\n");
    }

    @Override
    protected String getFrameTitle() {
        return "Simple Server";
    }

    public static void main(String[] args) {
        new SimpleSocketServer().setVisible(true);
    }

    private static final long serialVersionUID = 4288994465786972478L;
    private Socket relatedSocket;
    private ServerSocket serverSocket;
    private PrintStream outStream;
    private InputStreamReader isr;
    private BufferedReader inStream;
 }

クライアントクラスは次のとおりです: SimpleSocketClient.java

package com.loloof64.java_se.simple_socket;

import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;

import javax.swing.JOptionPane;

public class SimpleSocketClient extends SimpleSocketFrame {

    public SimpleSocketClient(){
        try {
            socket = new Socket(InetAddress.getLocalHost(), 12345);
            outStream = new PrintStream(socket.getOutputStream());

        isr = new InputStreamReader(socket.getInputStream());
            inStream = new BufferedReader(isr); 

            final InStreamRunnable inStreamRunnable = new InStreamRunnable();
        Thread inStreamReaderThread = new Thread(inStreamRunnable);

            addWindowListener(new WindowAdapter() {

                @Override
                public void windowClosing(WindowEvent evt) {
                try {
                        inStream.close();
                } catch (IOException e2) {
                    e2.printStackTrace();
                }
                try {
                    isr.close();
                } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                outStream.close();
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                inStreamRunnable.stop();
                System.exit(0);
            }

        });
            inStreamReaderThread.start();
    } catch (IOException e) {
            JOptionPane.showMessageDialog(this, "Could not create the client !!!",
                    "Fatal error", JOptionPane.ERROR_MESSAGE);
            System.exit(1);
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new SimpleSocketClient().setVisible(true);
    }

private class InStreamRunnable implements Runnable {

    @Override
    public void run() {
            while (weMustGoOn){
            String line;
            try {
                line = inStream.readLine();
                      printedMessagesArea.setText(printedMessagesArea.getText()+line+"\n");
                } catch (IOException e) {

                }
            }
        }

    public void stop(){
        weMustGoOn = false;
    }

    private boolean weMustGoOn = true;

    } 

@Override
protected void addMessage(String s) {
    s = "Client> "+s;
    outStream.println(s);
    printedMessagesArea.setText(printedMessagesArea.getText()+s+"\n");
}

@Override
    protected String getFrameTitle() {
    return "Simple Client";
}

    private static final long serialVersionUID = 5468568598525947366L;
    private Socket socket;
    private PrintStream outStream;
    private InputStreamReader isr;
    private BufferedReader inStream;


 } 
4

2 に答える 2

2

後にfinallyブロックを追加してソケットを閉じる必要があります。その後、システム終了メソッドでプログラムを閉じることができます。trycatch

于 2013-03-28T00:04:58.780 に答える
2

無期限にブロックしている をReaders閉じるときにネットワーク入力を閉じようとしても、プログラムは停止しません。サーバーからの応答を待っているこの呼び出しでクライアントスレッドがブロックされているため、オブジェクトを閉じることができませんJFrameBufferedReaderInputStreamReaderreadLine

line = inStream.readLine();

コメントアウトまたは削除:

inStream.close();

isr.close();

Socketストリームを閉じるだけで十分です。

余談:マルチスレッド ネットワーク アプリケーションの Swing コンポーネントと対話する場合は、常にSwingWorkerを使用してください。SwingWorkersSwing コンポーネントと正しく対話するように設計されています。

于 2013-03-28T00:17:25.240 に答える