内容:
今天看了一个聊天室的代码,发现其中的很多内容在学控制反转,和MVC模式的时候学过了,

不过线程类没接触,

代码的原地址:

下面是阅读时在代码上加的注释:

客户端:

 

public class Client extends Frame{  //Frame是带有边框和标题的顶层窗口,父类是Window类;
	TextField tf =new TextField();  //文本框,只有一行可写;
	TextArea  ta =new TextArea();  //多行输入框;
	Socket s =null;  //socket可以理解为一个IP地址加一个端口,客户端需要定义一个用于放送信息的socket对象;
	DataOutputStream dos =null;  //数据操作流,这是由于数据输出的类;
	DataInputStream dis =null;  //数据输入;
	boolean bConnected =false;   //应该是判断客户端是否与服务端相连;
	recvThread r =new recvThread();  //线程类,不太清楚;
	public static void main(String[] args) {
        new Client().creatFrame();
    }
	private void creatFrame() {
		this.setBounds(300, 300, 300, 300);  //设置窗口大小
		ta.setEditable(false); //字面意思,设置选项不可编辑;
		this.add(tf, BorderLayout.SOUTH);//后面这个有点印象,是将窗口分成五个区域,这句话的意思是将一个文本框(tf)加到南部;
		this.add(ta, BorderLayout.NORTH);//把ta放到client的北部;
		this.addWindowListener(new WindowAdapter() { //响应关闭窗口事件,采用是事情接听器;
            public void windowClosing(WindowEvent e) {
            	/*指示窗口发生改变的低级别事件,
            	当打开、关闭、激活、停用、图标化或取消图标化 Window 对象时,
            	或者焦点转移到 Window 内或移出 Window 时,由 Window 对象生成此低级别事件。*/
                disconnect();
                System.exit(0);
            }
        });
		tf.addActionListener(new tfListener()); //响应输入事件,加一个接听器;
	        this.pack();  //这个pack是打包的意思?
	        this.setVisible(true); //可见
	        connect();
	        new Thread(r).start();
	}
	 public void connect() {
	        try {
	            s = new Socket("127.0.0.1", 8888); //建立客户端对象
	            dos = new DataOutputStream(s.getOutputStream());
	            dis = new DataInputStream(s.getInputStream());
	            bConnected = true;
	        } catch (UnknownHostException e) {  //判断是否知道主机地址
	            e.printStackTrace();//在命令行打印异常信息在程序中出错的位置及原因;
	        } catch (IOException e) {  //判断IO流异常,且由于IO包括UnknownHost,所以必须写后面;
	            e.printStackTrace();
	        }
	    }
	 public void disconnect() { //窗口关闭时关闭客户端,输入,输出
	        try {
	            dos.close();
	            dis.close();
	            s.close();
	        } catch (IOException e) {
	            e.printStackTrace();
	        }
	    }
	 class tfListener implements ActionListener { //输入框实现的接口,响应输入事件
	        public void actionPerformed(ActionEvent e) {
	            String str = tf.getText();  //获取文本框中的类
	            ta.setText(str);  //在文本中加文本
	            tf.setText("");
	            try {
	                dos.writeUTF(str);  //这里的UTF是unicode的UTF-8编码;
	                dos.flush();  //清空
	                dos.close();
	            } catch (IOException e1) {
	                e1.printStackTrace();
	            }
	        }
	    }
	 class recvThread implements Runnable { //客户端线程接收数据
	        public void run() {
	            try {
	                while (bConnected) {
	                    String str;
	                    str = dis.readUTF(); //拿到数据
	                    ta.setText(ta.getText() + str + '\n');//显示到显示框中
	                }
	            } catch (SocketException e) { //这里一般是服务端或用户端一方主动断开连接产生的异常;
	                System.out.println("退出了");
	            } catch (IOException e1) {
	                e1.printStackTrace();
	            }
	        }
	    }

}

客户端:

 

 

public class Server {
	boolean started = false;
    ServerSocket ss = null;
    List<ChatClient> clients = new ArrayList<ChatClient>(); //保存客户端线程类
    public static void main(String[] args) {
        new Server().start();
    }
	void start() {
        try {
            ss = new ServerSocket(8888); //建立服务端对象
            started = true;
        } catch (BindException e) { //地址已在使用
            System.out.println("端口使用中");
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            while (started) {
                Socket s = ss.accept(); //接收客户端
                ChatClient c = new ChatClient(s);
                System.out.println("客戶端接收成功");
                new Thread(c).start(); //启动线程
                clients.add(c); //添加线程类
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                ss.close();
            } catch (IOException e) {
                // TODO 自动生成 catch 块
                e.printStackTrace();
            }
        }
    }
    class ChatClient implements Runnable { //建立客户端线程接收,发送数据
        private Socket s;
        DataInputStream dis = null;
        DataOutputStream dos = null;
        boolean bConnected = false;
        public ChatClient(Socket s) {
            this.s = s;
            try {
                dis = new DataInputStream(s.getInputStream());
                dos = new DataOutputStream(s.getOutputStream());
                bConnected = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        void send(String str) {
            try {
                dos.writeUTF(str);
            } catch (SocketException e) {
                System.out.println("對方退出了");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        public void run() {
            try {
                while (bConnected) {
                    String str = dis.readUTF();
                    System.out.println(str);
                    for (int i = 0; i < clients.size(); i++) {
                        ChatClient c = clients.get(i);
                        c.send(str);
                    }
                }
            } catch (EOFException e) {
                System.out.println("客戶端退出了");
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (dis != null)
                    if (s != null)
                        try {
                            dis.close();
                            s.close();
                            dos.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
            }
        }
    }

}