有人可以通过以下代码帮助我理解服务器在java中的工作方式

时间:2014-08-08 05:56:54

标签: java client

这是一个简单的聊天服务器和客户端,我从一本书中读到并且我无法理解某些代码,有人可以帮我解决这个问题

这是客户端代码

public class ChatClient {
JTextArea incoming;
JTextField outgoing;
BufferedReader reader;
PrintWriter writer;
Socket sock;

public static void main(String[] args) {
    ChatClient client = new ChatClient();
    client.go();

}

public void go() {
    JFrame frame = new JFrame();
    JPanel mainPanel = new JPanel();
    incoming = new JTextArea(15, 50);
    incoming.setLineWrap(true);
    incoming.setWrapStyleWord(true);
    incoming.setEditable(false);
    JScrollPane qScroller = new JScrollPane(incoming);
    qScroller
            .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    qScroller
            .setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    outgoing = new JTextField(20);
    JButton sendButton = new JButton("send");
    sendButton.addActionListener(sendButtonListener);
    mainPanel.add(qScroller);
    mainPanel.add(outgoing);
    mainPanel.add(sendButton);
    setUpNetworking();
    Thread readerThread = new Thread(new IncomingReader());
    readerThread.start();
    frame.add(mainPanel);
    frame.setSize(400, 500);
    frame.setVisible(true);

}

private void setUpNetworking() {
    try {
        sock = new Socket("127.0.0.1", 5000);
        InputStreamReader streamReader = new InputStreamReader(
                sock.getInputStream());
        reader = new BufferedReader(streamReader);
        writer = new PrintWriter(sock.getOutputStream());
        System.out.println("connected");
    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

ActionListener sendButtonListener = new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        writer.println(outgoing.getText());
        writer.flush();
        outgoing.setText("");
        outgoing.requestFocus();

    }

};

public class IncomingReader implements Runnable {

    @Override
    public void run() {
        String message;
        try {
            while ((message = reader.readLine()) != null) {

                System.out.println("read " + message);
                incoming.append(message + "\n");
            }

            System.out.println("ggggggggg");

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

}

我理解困难的部分是这一部分:

public void run() {
        String message;
        try {
            while ((message = reader.readLine()) != null) {

                System.out.println("read " + message);
                incoming.append(message + "\n");
            }



        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

在这部分中,只要我们从服务器读取的内容不是Null就运行代码,我的问题就是在我们启动线程后立即从服务器读取的第一件事因为我们还没有写任何东西,因此,打破了循环,这将是空的吗? 喜欢什么时候消息等于Null?

这是任何想要阅读它的服务器代码

public class ChatServer {
ArrayList clientOutputStreams;

public class ClientHandler implements Runnable {
    BufferedReader reader;
    Socket sock;

    public ClientHandler(Socket clientSocket) {
        try {
            sock = clientSocket;
            InputStreamReader isReader = new InputStreamReader(
                    sock.getInputStream());
            reader = new BufferedReader(isReader);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void run() {
        String message;
        try {
            while ((message = reader.readLine()) != null) {
                System.out.println("read " + message);
                tellEveryone(message);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

public static void main(String[] args) {
    new ChatServer().go();
}

public void go() {
    clientOutputStreams = new ArrayList();
    try {
        ServerSocket serverSock = new ServerSocket(5000);
        while (true) {
            Socket clientSocket = serverSock.accept();
            PrintWriter writer = new PrintWriter(
                    clientSocket.getOutputStream());
            clientOutputStreams.add(writer);
            Thread t = new Thread(new ClientHandler(clientSocket));
            t.start();
            System.out.println("got a connection");
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

public void tellEveryone(String message) {
    Iterator it = clientOutputStreams.iterator();
    while (it.hasNext()) {
        try {
            PrintWriter writer = (PrintWriter) it.next();
            writer.println(message);
            writer.flush();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

}

对我来说更合乎逻辑的方法是使用while循环并一直检查服务器,等待这样的消息:

while(true){
    if ((message = reader.readLine()) != null){
        System.out.println("read " + message);
        incoming.append(message + "\n");
    }
}

1 个答案:

答案 0 :(得分:1)

  

在我们启动主题时,我们从服务器读取的第一件事就是Nul​​l,因为我们还没有写任何东西

我认为你已经部分地回答了你自己的问题。当null到达EOF时会从BufferedReader#read返回EOF,因此,由于read标记尚未到达,EOF方法将会阻止,直到有任何内容为止要阅读或达到IOException

来自JavaDocs ...

  

public String readLine()
                 抛出IOException

  读一行文字。一条线被认为是换行(' \ n'),回车(' \ r')或回车后紧接着换行符中的任何一条终止。

  返回:
  包含该行内容的字符串,不包括任何行终止>字符或null 如果已达到结束

循环实际上是无限的。这将破坏的唯一方法是关闭基础流,这可能会导致{{1}}

你从哪本书中得到这个?这不是一个很好的例子