1

Java の readLine() に問題があります。サーバーとクライアントがあります。クライアントからサーバーにメッセージを送信したい。問題は、最初にクライアントが JTextField にテキストを挿入する必要があり、送信を押してからサーバーに送信してクライアントからの入力を読み取る必要がありますが、サーバーはクライアントからの入力を待たずに null を読み取ることです。しかし、 readLine() は、何かを読み取るまでブロックされると読みましたが、この場合、なぜそれが起こらないのですか?

ここで、サーバーに接続して JFrame を作成します。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class StartingPoint {

private static PrintWriter out;
private static BufferedReader in;

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                connectToServer();
                createAndShowGui();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
}

public static void createAndShowGui() throws IOException {
    View frame = new View(out, in);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setLocationByPlatform(true);
    frame.setVisible(true);
}

public static void connectToServer() throws IOException {
    String serverAddress = "127.0.0.1";

    int PORT = 8100;

    Socket clientSocket = null;
    out = null;
    in = null;

    try {
        clientSocket = new Socket(serverAddress, PORT);
        out = new PrintWriter(clientSocket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(
                clientSocket.getInputStream()));
    } catch (UnknownHostException e) {
        System.err.println("Could not connect to the server \n" + e);
        System.exit(1);
    } finally {
        if (out != null)
            out.close();
        if (in != null)
            in.close();
        if (clientSocket != null)
            clientSocket.close();
    }
}
}

JFrame の実装は次のとおりです。

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class View extends JFrame {

private JButton button;
private JTextField field;
private JPanel gui;

public View(final PrintWriter out, final BufferedReader in) throws IOException {

    button = new JButton("Send");
    field = new JTextField();

    gui = new JPanel(new GridLayout(1, 0, 10, 10));

    gui.add(button);
    gui.add(field);

    add(gui);

    button.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            out.println(field.getText());

            try {
                System.out.println(in.readLine());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });
}
}

サーバーは次のとおりです。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class SimpleServer extends Thread {

public static final int PORT = 8100;
private static ServerSocket serverSocket = null;

private Socket clientSocket = null;

public void run() {
    String receive, answer;
    try {
        BufferedReader in = new BufferedReader(new InputStreamReader(
                clientSocket.getInputStream()));

        PrintWriter out = new PrintWriter(clientSocket.getOutputStream());

        receive = in.readLine();
        System.out.println("[server]" +  receive);
        answer = "hello " + receive;
        out.println(answer);
        out.flush();

    } catch (IOException e) {
        System.err.println("IO error \n" + e);
    } finally {
        try {
            clientSocket.close();
        } catch (IOException e) {
            System.err.println("Close socket error \n" + e);
        }

    }
}

public SimpleServer() throws IOException {

    while (true) {
        serverSocket = new ServerSocket(PORT);
        try {
            clientSocket = serverSocket.accept();

            new Thread(this).start();

        } finally {
            serverSocket.close();
        }
    }
}

public static void main(String[] args) throws IOException {
    SimpleServer server = new SimpleServer();
}
}
4

2 に答える 2

6

メソッドconnectToServer()は接続を開き、ストリームを作成し、... 戻る前にそれらを閉じます。もちろん、サーバーはすぐに終了を確認nullし、最初のreadLine()呼び出しに戻ります。


意味を理解せずに「finally ブロックで閉じる」パターンをコピーしたのではないかと思います。そこで、次のように説明します。

これは通常のパターンです:

InputStream is = null;
try {
    is = new FileInputStream(someFile);
    // read the stream
} finally {
    if (is != null) {
        is.close();
    }
}

上記のコードの目的は、InputStream が常に閉じていることを確認することです。より正確には、 try/finally が終了する前に常に閉じられます。

これは一般的には良いことです。ただし、コードの目的が、このコードのビットが完了した後に使用されるストリームを開くことである場合、ここでストリームを閉じることは自滅的です。

InputStream is = null;
try {
    is = new FileInputStream(someFile);
} finally {
    if (is != null) {
        is.close();
    }
}
// read the stream ... OOOPS!  We've already closed it!!

runしたがって、これを元のコードに戻すには、次の行に沿って、try/finally/close をメソッドに移動する必要があります。

    public void run() {
        try {
            connectToServer();
            createAndShowGui();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null)
                out.close();
            if (in != null)
                in.close();
            if (clientSocket != null)
                clientSocket.close();
        } 
    }

IOExceptionまた、呼び出しごとにスローされる可能性があるものをキャッチして (おそらく) 無視する必要がありclose()ます。

于 2013-05-06T13:29:08.813 に答える
2

Javadoc forBufferedReader.readLine() はそのようなことは何も言いません:

戻り値:String行終了文字を含まない、行の内容を含む 、またはストリームの終わりに達した場合は null

コードでは、connectToServer() で接続を開き、それを閉じるため、サーバーはストリームの終わりを認識します

于 2013-05-06T13:28:31.903 に答える