• JavaSE聊天室


    今天学习了一下简单聊天程序(类似QQ那种)的编写过程,从最初的0.1版本到最后的1.3版本,功能不断地增强,下面对一天的学习内容进行梳理。

    版本0.1

    我们的需求是显示一个窗体,其他什么也不用做,其他功能逐步添加,我们这里用的就是AWT中的Frame;

    具体代码实现:

     1 import java.awt.*;
     2 
     3 public class ChatClient extends Frame{
     4 
     5     /**
     6      * @param args
     7      */
     8     public static void main(String[] args) {
     9         new ChatClient().launchFrame();
    10     }
    11 
    12     /**
    13      * Version 0.1
    14      */
    15     public void launchFrame(){
    16         //设置Frame位置
    17         setLocation(400, 300);
    18         //设置Frame大小
    19         this.setSize(300, 300);
    20         //窗口可见
    21         setVisible(true);
    22     }
    23 }

    版本0.2

    我们的需求是在我们的Frame中添加两个部件TextField(用于输入)和TextArea(用于显示获取的内容),此时我们可以在输入框输入内容,但是显示框无法显示我们输入的内容.

     1 import java.awt.*;
     2 
     3 public class ChatClient extends Frame {
     4 
     5     TextField tfTxt = new TextField();
     6     TextArea taContent = new TextArea();
     7 
     8     public static void main(String[] args) {
     9         new ChatClient().launchFrame();
    10     }
    11 
    12     /**
    13      * Version 0.2
    14      */
    15     public void launchFrame() {
    16         // 设置Frame位置
    17         setLocation(400, 300);
    18         // 设置Frame大小
    19         this.setSize(300, 300);
    20         // 将输入框TextField加到Frame中,并放置到Frame布局的上面
    21         add(tfTxt, BorderLayout.SOUTH);
    22         // 将显示框TextArea加到Frame中,并放置到Frame布局的下面
    23         add(taContent, BorderLayout.NORTH);
    24         // 调整布局,处理多余空白框
    25         pack();
    26         // 窗口可见
    27         setVisible(true);
    28     }
    29 }

    版本0.3

    因为我们的版本0.2中,显示的窗体无法关闭(除非把程序停掉,我们这里不考虑这种做法),我们添加窗口监听,使我们可以通过点击窗体的(X)符号进行关闭;

     1 import java.awt.*;
     2 import java.awt.event.*;
     3 
     4 public class ChatClient extends Frame {
     5 
     6     TextField tfTxt = new TextField();
     7     TextArea taContent = new TextArea();
     8 
     9     public static void main(String[] args) {
    10         new ChatClient().launchFrame();
    11     }
    12 
    13     /**
    14      * Version 0.3:添加窗口关闭的功能
    15      */
    16     public void launchFrame() {
    17         // 设置Frame位置
    18         setLocation(400, 300);
    19         // 设置Frame大小
    20         this.setSize(300, 300);
    21         // 将输入框TextField加到Frame中,并放置到Frame布局的上面
    22         add(tfTxt, BorderLayout.SOUTH);
    23         // 将显示框TextArea加到Frame中,并放置到Frame布局的下面
    24         add(taContent, BorderLayout.NORTH);
    25         // 调整布局,处理多余空白框
    26         pack();
    27         //添加窗口监听
    28         this.addWindowListener(new WindowAdapter() {
    29 
    30             @Override
    31             public void windowClosing(WindowEvent e) {
    32                 System.exit(0);
    33             }        
    34         });
    35         
    36         // 窗口可见
    37         setVisible(true);
    38     }
    39 }

    版本0.4

    我们实现的功能是将输入框输入的内容显示到显示框TextArea中,

     1 import java.awt.*;
     2 import java.awt.event.*;
     3 
     4 public class ChatClient extends Frame {
     5 
     6     TextField tfTxt = new TextField();
     7     TextArea taContent = new TextArea();
     8 
     9     public static void main(String[] args) {
    10         new ChatClient().launchFrame();
    11     }
    12 
    13     /**
    14      * Version 0.4
    15      */
    16     public void launchFrame() {
    17         // 设置Frame位置
    18         setLocation(400, 300);
    19         // 设置Frame大小
    20         this.setSize(300, 300);
    21         // 将输入框TextField加到Frame中,并放置到Frame布局的上面
    22         add(tfTxt, BorderLayout.SOUTH);
    23         // 将显示框TextArea加到Frame中,并放置到Frame布局的下面
    24         add(taContent, BorderLayout.NORTH);
    25         // 调整布局,处理多余空白框
    26         pack();
    27         // 添加窗口监听
    28         this.addWindowListener(new WindowAdapter() {
    29 
    30             @Override
    31             public void windowClosing(WindowEvent e) {
    32                 System.exit(0);
    33             }
    34         });
    35 
    36         // 将监听器类TFListener添加到输入框TextField中
    37         tfTxt.addActionListener(new TFListener());
    38         // 窗口可见
    39         setVisible(true);
    40     }
    41 
    42     // 建立私有的监听器类,TextField监听:将TextField内容放置到TextArea
    43     private class TFListener implements ActionListener {
    44 
    45         @Override
    46         public void actionPerformed(ActionEvent e) {
    47             //获得输入框的内容,并去除两端的空格
    48             String s = tfTxt.getText().trim();
    49             //将获取的输入内容放置到TextArea中
    50             taContent.setText(s);
    51             //每次输入结束,将输入框置空
    52             tfTxt.setText("");
    53         }
    54     }
    55 }

    版本0.5

    相比版本0.4,我们添加了Server端,使得Server作为中转站,把我们输入的内容显示在其他连接到Server端的客户端的的显示框中;

    ChatClient

     1 import java.awt.*;
     2 import java.awt.event.*;
     3 
     4 public class ChatClient extends Frame {
     5 
     6     TextField tfTxt = new TextField();
     7     TextArea taContent = new TextArea();
     8 
     9     public static void main(String[] args) {
    10         new ChatClient().launchFrame();
    11     }
    12 
    13     /**
    14      * Version 0.5:处理输入框
    15      */
    16     public void launchFrame() {
    17         // 设置Frame位置
    18         setLocation(400, 300);
    19         // 设置Frame大小
    20         this.setSize(300, 300);
    21         // 将输入框TextField加到Frame中,并放置到Frame布局的上面
    22         add(tfTxt, BorderLayout.SOUTH);
    23         // 将显示框TextArea加到Frame中,并放置到Frame布局的下面
    24         add(taContent, BorderLayout.NORTH);
    25         // 调整布局,处理多余空白框
    26         pack();
    27         // 添加窗口监听
    28         this.addWindowListener(new WindowAdapter() {
    29 
    30             @Override
    31             public void windowClosing(WindowEvent e) {
    32                 System.exit(0);
    33             }
    34         });
    35 
    36         // 将监听器类TFListener添加到输入框TextField中
    37         tfTxt.addActionListener(new TFListener());
    38         // 窗口可见
    39         setVisible(true);
    40     }
    41 
    42     // 建立私有的监听器类,TextField监听:将TextField内容放置到TextArea
    43     private class TFListener implements ActionListener {
    44 
    45         @Override
    46         public void actionPerformed(ActionEvent e) {
    47             // 获得输入框的内容,并去除两端的空格
    48             String s = tfTxt.getText().trim();
    49             // 将获取的输入内容放置到TextArea中
    50             taContent.setText(s);
    51             // 每次输入结束,将输入框置空
    52             tfTxt.setText("");
    53         }
    54     }
    55 }
    View Code

    Server

     1 import java.io.IOException;
     2 import java.net.*;
     3 
     4 //server端
     5 public class ChatServer {
     6 
     7     /**
     8      * @param args
     9      */
    10     public static void main(String[] args) {
    11         try {
    12             ServerSocket ss = new ServerSocket(8888);
    13             while(true){
    14                 Socket s=ss.accept();
    15 System.out.println("a clint connected");
    16             }
    17         } catch (IOException e) {
    18             e.printStackTrace();
    19         }
    20     }
    21 }
    View Code

    此时,我们可以运行多个客户端,但是每个客户端输入的内容在其他客户端都无法显示,他们都是孤立的,还没有与Server端建立连接;

    版本0.6

    ChatClient

     1 import java.awt.*;
     2 import java.awt.event.*;
     3 import java.io.*;
     4 import java.net.*;
     5 
     6 public class ChatClient extends Frame {
     7     Socket s = null;
     8 
     9     TextField tfTxt = new TextField();
    10 
    11     TextArea taContent = new TextArea();
    12 
    13     public static void main(String[] args) {
    14         new ChatClient().launchFrame(); 
    15     }
    16 
    17     /**
    18      * Version 0.6
    19      */
    20     public void launchFrame() {
    21         setLocation(400, 300);
    22         this.setSize(300, 300);
    23         add(tfTxt, BorderLayout.SOUTH);
    24         add(taContent, BorderLayout.NORTH);
    25         pack();
    26         this.addWindowListener(new WindowAdapter() {
    27 
    28             @Override
    29             public void windowClosing(WindowEvent arg0) {
    30                 System.exit(0);
    31             }
    32             
    33         });
    34         tfTxt.addActionListener(new TFListener());
    35         setVisible(true);
    36         connect();
    37     }
    38     
    39     public void connect() {
    40         try {
    41             s = new Socket("127.0.0.1", 8888);
    42 System.out.println("connected!");
    43         } catch (UnknownHostException e) {
    44             e.printStackTrace();
    45         } catch (IOException e) {
    46             e.printStackTrace();
    47         }
    48         
    49     }
    50     
    51     private class TFListener implements ActionListener {
    52 
    53         public void actionPerformed(ActionEvent e) {
    54             String str = tfTxt.getText().trim();
    55             taContent.setText(str);
    56             tfTxt.setText("");
    57             
    58             try {
    59                 DataOutputStream dos = new DataOutputStream(s.getOutputStream());
    60                 dos.writeUTF(str);
    61                 dos.flush();
    62                 dos.close();
    63             } catch (IOException e1) {
    64                 e1.printStackTrace();
    65             }
    66             
    67         }
    68         
    69     }
    70 
    71 }
    View Code

    Server

     1 import java.io.*;
     2 import java.net.*;
     3 
     4 public class ChatServer {
     5 
     6     public static void main(String[] args) {
     7         try {
     8             // 服务器端需要创建监听端口的 ServerSocket, ServerSocket 负责接收客户连接请求
     9             ServerSocket ss = new ServerSocket(8888);
    10             while (true) {
    11                 //服务器端应对客户端的每一个连接建立一个新的Socket(重要)
    12                 Socket s = ss.accept();
    13                 // 当有客户端连接上时,打印连接信息
    14                 System.out.println("a client connected!");
    15 
    16                 //获取Socket s的输入流
    17                 DataInputStream dis = new DataInputStream(s.getInputStream());
    18                 //获取输入流中的信息
    19                 String str = dis.readUTF();
    20                 System.out.println(str);
    21                 //关闭流操作
    22                 dis.close();
    23             }
    24         } catch (IOException e) {
    25             e.printStackTrace();
    26         }
    27     }
    28 
    29 }
    View Code

    我们此时客户端输入的内容可以显示在Server端的控制台上,每个连接上的Client的输入只有第一次输入可以显示在控制台,每个客户端不可以接收其他客户端的信息。并且当我们某些关闭处于连接状态的客户端的时候Server端会报Socket异常;

    版本0.7

    ChatClient

     1 import java.awt.*;
     2 import java.awt.event.*;
     3 import java.io.DataOutputStream;
     4 import java.io.IOException;
     5 import java.net.*;
     6 
     7 public class ChatClient extends Frame {
     8 
     9     // 暴露Socket
    10     Socket s = null;
    11     TextField tfTxt = new TextField();
    12     TextArea taContent = new TextArea();
    13 
    14     public static void main(String[] args) {
    15         new ChatClient().launchFrame();
    16     }
    17 
    18     /**
    19      * Version 0.7
    20      */
    21     public void launchFrame() {
    22         // 设置Frame位置
    23         setLocation(400, 300);
    24         // 设置Frame大小
    25         this.setSize(300, 300);
    26         // 将输入框TextField加到Frame中,并放置到Frame布局的上面
    27         add(tfTxt, BorderLayout.SOUTH);
    28         // 将显示框TextArea加到Frame中,并放置到Frame布局的下面
    29         add(taContent, BorderLayout.NORTH);
    30         // 调整布局,处理多余空白框
    31         pack();
    32         // 添加窗口监听
    33         this.addWindowListener(new WindowAdapter() {
    34 
    35             @Override
    36             public void windowClosing(WindowEvent e) {
    37                 System.exit(0);
    38             }
    39         });
    40 
    41         // 将监听器类TFListener添加到输入框TextField中
    42         tfTxt.addActionListener(new TFListener());
    43         // 窗口可见
    44         setVisible(true);
    45         connect();
    46     }
    47 
    48     // 建立連接的方法
    49     public void connect() {
    50         try {
    51             s = new Socket("127.0.0.1", 8888);
    52             System.out.println("connected!");
    53         } catch (UnknownHostException e) {
    54             e.printStackTrace();
    55         } catch (IOException e) {
    56             e.printStackTrace();
    57         }
    58     }
    59 
    60     // 建立私有的监听器类,TextField监听:将TextField内容放置到TextArea
    61     private class TFListener implements ActionListener {
    62 
    63         @Override
    64         public void actionPerformed(ActionEvent e) {
    65             // 获得输入框的内容,并去除两端的空格
    66             String string = tfTxt.getText().trim();
    67             // 将获取的输入内容放置到TextArea中
    68             taContent.setText(string);
    69             // 每次输入结束,将输入框置空
    70             tfTxt.setText("");
    71             try {
    72                 System.out.println(s);
    73                 DataOutputStream dos = new DataOutputStream(s.getOutputStream());
    74                 dos.writeUTF(string);
    75                 dos.flush();
    76                 dos.close();
    77             } catch (IOException e1) {
    78                 e1.printStackTrace();
    79             }
    80 
    81         }
    82     }
    83 }
    View Code

    Server

     1 import java.io.DataInputStream;
     2 import java.io.IOException;
     3 import java.net.*;
     4 
     5 //server端
     6 public class ChatServer {
     7 
     8     /**
     9      * @param args
    10      */
    11     public static void main(String[] args) {
    12         try {
    13             ServerSocket ss = new ServerSocket(8888);
    14             while(true){
    15                 Socket s=ss.accept();
    16 System.out.println("a clint connected");
    17             DataInputStream dis=new DataInputStream(s.getInputStream());
    18             String str=dis.readUTF();
    19             System.out.println(str);
    20             dis.close();
    21             }
    22         } catch (IOException e) {
    23             e.printStackTrace();
    24         }
    25     }
    26 
    27 }
    View Code

    相较于版本0.6,做了一些调试工作,每次打印System.out.println(s);观察出错信息,关闭客户端时,仍然会出现Socket is closed异常

    版本0.8

    ChatClient

     1 import java.awt.*;
     2 import java.awt.event.*;
     3 import java.io.DataOutputStream;
     4 import java.io.IOException;
     5 import java.net.*;
     6 public class ChatClient extends Frame {
     7 
     8     //暴露Socket
     9     Socket s=null;
    10     DataOutputStream dos=null;
    11     TextField tfTxt = new TextField();
    12     TextArea taContent = new TextArea();
    13 
    14     public static void main(String[] args) {
    15         new ChatClient().launchFrame();
    16     }
    17 
    18     /**
    19      * Version 0.8
    20      */
    21     public void launchFrame() {
    22         // 设置Frame位置
    23         setLocation(400, 300);
    24         // 设置Frame大小
    25         this.setSize(300, 300);
    26         // 将输入框TextField加到Frame中,并放置到Frame布局的上面
    27         add(tfTxt, BorderLayout.SOUTH);
    28         // 将显示框TextArea加到Frame中,并放置到Frame布局的下面
    29         add(taContent, BorderLayout.NORTH);
    30         // 调整布局,处理多余空白框
    31         pack();
    32         // 添加窗口监听
    33         this.addWindowListener(new WindowAdapter() {
    34 
    35             @Override
    36             public void windowClosing(WindowEvent e) {
    37                 //窗口关闭的时候释放连接资源
    38                 disconnect();
    39                 System.exit(0);
    40             }
    41         });
    42 
    43         // 将监听器类TFListener添加到输入框TextField中
    44         tfTxt.addActionListener(new TFListener());
    45         // 窗口可见
    46         setVisible(true);
    47         connect();
    48     }
    49     //建立連接的方法
    50     public void connect(){
    51         try {
    52             s=new Socket("127.0.0.1",8888);
    53             dos=new DataOutputStream(s.getOutputStream());
    54 System.out.println("connected!");            
    55         } catch (UnknownHostException e) {
    56             e.printStackTrace();
    57         } catch (IOException e) {
    58             e.printStackTrace();
    59         }
    60     }
    61     public void disconnect(){
    62         try {
    63             dos.close();
    64             s.close();
    65         } catch (Exception e) {
    66             e.printStackTrace();
    67         }
    68     }
    69 
    70     // 建立私有的监听器类,TextField监听:将TextField内容放置到TextArea
    71     private class TFListener implements ActionListener {
    72 
    73         @Override
    74         public void actionPerformed(ActionEvent e) {
    75             // 获得输入框的内容,并去除两端的空格
    76             String string = tfTxt.getText().trim();
    77             // 将获取的输入内容放置到TextArea中
    78             taContent.setText(string);
    79             // 每次输入结束,将输入框置空
    80             tfTxt.setText("");
    81             try {
    82 System.out.println(s);        
    83 //不同每次都获取一次连接
    84 //                DataOutputStream dos=new DataOutputStream(s.getOutputStream());
    85                 dos.writeUTF(string);
    86                 dos.flush();
    87 //                dos.close();
    88             } catch (IOException e1) {
    89                 e1.printStackTrace();
    90             }
    91             
    92         }
    93     }
    94 }
    View Code

    Server

     1 import java.io.DataInputStream;
     2 import java.io.IOException;
     3 import java.net.*;
     4 
     5 //server端
     6 public class ChatServer {
     7 
     8     public static void main(String[] args) {
     9         //服务器端是否已经启动
    10         boolean started=false;
    11         try {
    12             ServerSocket ss = new ServerSocket(8888);
    13             //服务器端启动以后,started=true
    14             started=true;
    15             //服务器端启动以后才能不断接收客户端的连接
    16             while(started){
    17                 //定义boolean类型的变量,客户端时候建立连接
    18                 boolean bConnected;
    19                 Socket s=ss.accept();
    20 System.out.println("a clint connected");
    21             //客户端时候建立连接以后,bConnected=true;
    22             bConnected=true; 
    23             DataInputStream dis=new DataInputStream(s.getInputStream());
    24             //客户端建立连接以后,不断的接收写来的数据
    25             while(bConnected){        
    26                 String str=dis.readUTF();
    27                 System.out.println(str);
    28             }
    29             //没有连接上,关闭dis,释放资源
    30             dis.close();
    31             }
    32         } catch (IOException e) {
    33             e.printStackTrace();
    34         }
    35     }
    36 
    37 }
    View Code

    我们在这一版本中添加了连接标志,运行测试发现Server端可以接收多个客户端的连接,但是只能将第一个连接的客户端的输入显示在控制台,其他客户端依然无法获取到其他客户端的内容,仍会出现异常

    版本0.9

    ChatClient

     1 import java.awt.*;
     2 import java.awt.event.*;
     3 import java.io.DataOutputStream;
     4 import java.io.IOException;
     5 import java.net.*;
     6 public class ChatClient extends Frame {
     7 
     8     //暴露Socket
     9     Socket s=null;
    10     DataOutputStream dos=null;
    11     TextField tfTxt = new TextField();
    12     TextArea taContent = new TextArea();
    13 
    14     public static void main(String[] args) {
    15         new ChatClient().launchFrame();
    16     }
    17 
    18     /**
    19      * Version 0.9
    20      */
    21     public void launchFrame() {
    22         // 设置Frame位置
    23         setLocation(400, 300);
    24         // 设置Frame大小
    25         this.setSize(300, 300);
    26         // 将输入框TextField加到Frame中,并放置到Frame布局的上面
    27         add(tfTxt, BorderLayout.SOUTH);
    28         // 将显示框TextArea加到Frame中,并放置到Frame布局的下面
    29         add(taContent, BorderLayout.NORTH);
    30         // 调整布局,处理多余空白框
    31         pack();
    32         // 添加窗口监听
    33         this.addWindowListener(new WindowAdapter() {
    34 
    35             @Override
    36             public void windowClosing(WindowEvent e) {
    37                 //窗口关闭的时候释放连接资源
    38                 disconnect();
    39                 System.exit(0);
    40             }
    41         });
    42 
    43         // 将监听器类TFListener添加到输入框TextField中
    44         tfTxt.addActionListener(new TFListener());
    45         // 窗口可见
    46         setVisible(true);
    47         connect();
    48     }
    49     //建立連接的方法
    50     public void connect(){
    51         try {
    52             s=new Socket("127.0.0.1",8888);
    53             dos=new DataOutputStream(s.getOutputStream());
    54 System.out.println("connected!");            
    55         } catch (UnknownHostException e) {
    56             e.printStackTrace();
    57         } catch (IOException e) {
    58             e.printStackTrace();
    59         }
    60     }
    61     public void disconnect(){
    62         try {
    63             dos.close();
    64             s.close();
    65         } catch (Exception e) {
    66             e.printStackTrace();
    67         }
    68     }
    69 
    70     // 建立私有的监听器类,TextField监听:将TextField内容放置到TextArea
    71     private class TFListener implements ActionListener {
    72 
    73         @Override
    74         public void actionPerformed(ActionEvent e) {
    75             // 获得输入框的内容,并去除两端的空格
    76             String string = tfTxt.getText().trim();
    77             // 将获取的输入内容放置到TextArea中
    78             taContent.setText(string);
    79             // 每次输入结束,将输入框置空
    80             tfTxt.setText("");
    81             try {
    82 System.out.println(s);        
    83 //不同每次都获取一次连接
    84 //                DataOutputStream dos=new DataOutputStream(s.getOutputStream());
    85                 dos.writeUTF(string);
    86                 dos.flush();
    87 //                dos.close();
    88             } catch (IOException e1) {
    89                 e1.printStackTrace();
    90             }
    91             
    92         }
    93     }
    94 }
    View Code

    Server

     1 import java.io.DataInputStream;
     2 import java.io.EOFException;
     3 import java.io.IOException;
     4 import java.net.*;
     5 
     6 //server端
     7 public class ChatServer {
     8 
     9     public static void main(String[] args) {
    10         //服务器端是否已经启动
    11         boolean started=false;
    12         ServerSocket ss = null;
    13         Socket s=null;
    14         DataInputStream dis=null;
    15         try {
    16             //可能会产生端口绑定异常
    17             ss = new ServerSocket(8888);
    18         }catch(BindException e){
    19             System.out.println("端口使用中");
    20             System.out.println("关闭相关程序,并重新运行");
    21             System.exit(0);
    22         }catch(IOException e){
    23             e.printStackTrace();
    24         }
    25         try {
    26             //服务器端启动以后,started=true
    27             started=true;
    28             //服务器端启动以后才能不断接收客户端的连接
    29             while(started){
    30                 //定义boolean类型的变量,客户端时候建立连接
    31                 boolean bConnected;
    32                 s=ss.accept();
    33 System.out.println("a clint connected");
    34             //客户端时候建立连接以后,bConnected=true;
    35             bConnected=true; 
    36             dis=new DataInputStream(s.getInputStream());
    37             //客户端建立连接以后,不断的接收写来的数据
    38             while(bConnected){
    39                 //readUTF是阻塞式的
    40                 String str=dis.readUTF();
    41                 System.out.println(str);
    42             }
    43             //没有连接上,关闭dis,释放资源
    44 //            dis.close();
    45             }
    46             //如果是因为客户端的关闭而导致的连接中断,则做这样的处理
    47         }catch(EOFException e){
    48             System.out.println("Client closed");
    49         //其他异常,直接打印异常信息
    50         }catch (IOException e) {
    51             e.printStackTrace();
    52         }finally{
    53             try {
    54                 if(dis!=null){    
    55                     dis.close();
    56                 }
    57                 if(s!=null){    
    58                     s.close();
    59                 }
    60             } catch (IOException e1) {
    61                 e1.printStackTrace();
    62             }
    63         }
    64     }
    65 
    66 }
    View Code

    之前的版本,当我们关闭客户端的时候都会发生异常,在这个版本中我们做了相应的处理,去捕获这个异常,并将连接资源的关闭工作进行细化;这里我们在客户端进行了处理:将DataOutputStream提到了全局变量的位置。不用每次都去获取一次Socket的输出流;

    版本1.0

    ChatClient

     1 import java.awt.*;
     2 import java.awt.event.*;
     3 import java.io.DataOutputStream;
     4 import java.io.IOException;
     5 import java.net.*;
     6 
     7 public class ChatClient extends Frame {
     8 
     9     // 暴露Socket
    10     Socket s = null;
    11     DataOutputStream dos = null;
    12     TextField tfTxt = new TextField();
    13     TextArea taContent = new TextArea();
    14 
    15     public static void main(String[] args) {
    16         new ChatClient().launchFrame();
    17     }
    18 
    19     /**
    20      * Version 1.0
    21      */
    22     public void launchFrame() {
    23         // 设置Frame位置
    24         setLocation(400, 300);
    25         // 设置Frame大小
    26         this.setSize(300, 300);
    27         // 将输入框TextField加到Frame中,并放置到Frame布局的上面
    28         add(tfTxt, BorderLayout.SOUTH);
    29         // 将显示框TextArea加到Frame中,并放置到Frame布局的下面
    30         add(taContent, BorderLayout.NORTH);
    31         // 调整布局,处理多余空白框
    32         pack();
    33         // 添加窗口监听
    34         this.addWindowListener(new WindowAdapter() {
    35 
    36             @Override
    37             public void windowClosing(WindowEvent e) {
    38                 // 窗口关闭的时候释放连接资源
    39                 disconnect();
    40                 System.exit(0);
    41             }
    42         });
    43 
    44         // 将监听器类TFListener添加到输入框TextField中
    45         tfTxt.addActionListener(new TFListener());
    46         // 窗口可见
    47         setVisible(true);
    48         connect();
    49     }
    50 
    51     // 建立連接的方法
    52     public void connect() {
    53         try {
    54             s = new Socket("127.0.0.1", 8888);
    55             dos = new DataOutputStream(s.getOutputStream());
    56             System.out.println("connected!");
    57         } catch (UnknownHostException e) {
    58             e.printStackTrace();
    59         } catch (IOException e) {
    60             e.printStackTrace();
    61         }
    62     }
    63 
    64     public void disconnect() {
    65         try {
    66             dos.close();
    67             s.close();
    68         } catch (Exception e) {
    69             e.printStackTrace();
    70         }
    71     }
    72 
    73     // 建立私有的监听器类,TextField监听:将TextField内容放置到TextArea
    74     private class TFListener implements ActionListener {
    75 
    76         @Override
    77         public void actionPerformed(ActionEvent e) {
    78             // 获得输入框的内容,并去除两端的空格
    79             String string = tfTxt.getText().trim();
    80             // 将获取的输入内容放置到TextArea中
    81             taContent.setText(string);
    82             // 每次输入结束,将输入框置空
    83             tfTxt.setText("");
    84             try {
    85                 System.out.println(s);
    86                 // 不同每次都获取一次连接
    87                 // DataOutputStream dos=new
    88                 // DataOutputStream(s.getOutputStream());
    89                 dos.writeUTF(string);
    90                 dos.flush();
    91                 // dos.close();
    92             } catch (IOException e1) {
    93                 e1.printStackTrace();
    94             }
    95 
    96         }
    97     }
    98 }
    View Code

    Server

     1 import java.io.DataInputStream;
     2 import java.io.EOFException;
     3 import java.io.IOException;
     4 import java.net.*;
     5 import java.security.Principal;
     6 
     7 //server端
     8 public class ChatServer {
     9 
    10     boolean started = false;
    11     ServerSocket ss = null;
    12 
    13     public static void main(String[] args) {
    14         new ChatServer().start();
    15     }
    16 
    17     public void start() {
    18 
    19         try {
    20             // 可能会产生端口绑定异常
    21             ss = new ServerSocket(8888);
    22             // 服务器端启动以后,started=true
    23             started = true;
    24         } catch (BindException e) {
    25             System.out.println("端口使用中");
    26             System.out.println("关闭相关程序,并重新运行");
    27             System.exit(0);
    28         } catch (IOException e) {
    29             e.printStackTrace();
    30         }
    31         try {
    32             // 服务器端启动以后才能不断接收客户端的连接
    33             while (started) {
    34                 Socket s = ss.accept();
    35                 // 不能在静态方法里new一个动态的类
    36                 Client c = new Client(s);
    37                 System.out.println("a clint connected");
    38                 new Thread(c).start();
    39             }
    40             // 如果是因为客户端的关闭而导致的连接中断,则做这样的处理
    41         } catch (IOException e) {
    42             e.printStackTrace();
    43 
    44         } finally {
    45             try {
    46                 ss.close();
    47             } catch (IOException e) {
    48                 e.printStackTrace();
    49             }
    50         }
    51     }
    52 
    53 }
    54 
    55 class Client implements Runnable {
    56     private Socket s;
    57     private DataInputStream dis = null;
    58     private boolean bConnected = false;
    59 
    60     public Client(Socket s) {
    61         this.s = s;
    62         try {
    63             dis = new DataInputStream(s.getInputStream());
    64             bConnected = true;
    65         }catch (IOException e) {
    66             e.printStackTrace();
    67 
    68         }
    69     }
    70 
    71     @Override
    72     public void run() {
    73         try {
    74             while (bConnected) {
    75                 String str = dis.readUTF();
    76                 System.out.println(str);
    77             }
    78         } catch (EOFException e) {
    79             System.out.println("Client closed");
    80         } catch (IOException e) {
    81             e.printStackTrace();
    82         } finally {
    83             try {
    84                 if (dis != null) {
    85                     dis.close();
    86                 }
    87                 if (s != null) {
    88                     s.close();
    89                 }
    90             } catch (Exception e2) {
    91                 e2.printStackTrace();
    92             }
    93         }
    94 
    95     }
    96 
    97 }
    View Code

    版本1.0可以处理多个客户端同时连接并显示其输入内容的效果;将每个客户端封装到一个独立的线程中;

    版本1.1

    ChatClient

      1 import java.awt.*;
      2 import java.awt.event.*;
      3 import java.io.DataOutputStream;
      4 import java.io.IOException;
      5 import java.net.*;
      6 import java.util.*;
      7 import java.util.List;
      8 //转发给
      9 public class ChatClient extends Frame {
     10 
     11     // 暴露Socket
     12     Socket s = null;
     13     DataOutputStream dos = null;
     14     TextField tfTxt = new TextField();
     15     TextArea taContent = new TextArea();
     16 
     17     public static void main(String[] args) {
     18         new ChatClient().launchFrame();
     19     }
     20 
     21     /**
     22      * Version 1.1:转发给其他客户端,保存socket连接,用集合
     23      */
     24     public void launchFrame() {
     25         // 设置Frame位置
     26         setLocation(400, 300);
     27         // 设置Frame大小
     28         this.setSize(300, 300);
     29         // 将输入框TextField加到Frame中,并放置到Frame布局的上面
     30         add(tfTxt, BorderLayout.SOUTH);
     31         // 将显示框TextArea加到Frame中,并放置到Frame布局的下面
     32         add(taContent, BorderLayout.NORTH);
     33         // 调整布局,处理多余空白框
     34         pack();
     35         // 添加窗口监听
     36         this.addWindowListener(new WindowAdapter() {
     37 
     38             @Override
     39             public void windowClosing(WindowEvent e) {
     40                 // 窗口关闭的时候释放连接资源
     41                 disconnect();
     42                 System.exit(0);
     43             }
     44         });
     45 
     46         // 将监听器类TFListener添加到输入框TextField中
     47         tfTxt.addActionListener(new TFListener());
     48         // 窗口可见
     49         setVisible(true);
     50         connect();
     51     }
     52 
     53     // 建立連接的方法
     54     public void connect() {
     55         try {
     56             s = new Socket("127.0.0.1", 8888);
     57             dos = new DataOutputStream(s.getOutputStream());
     58             System.out.println("connected!");
     59         } catch (UnknownHostException e) {
     60             e.printStackTrace();
     61         } catch (IOException e) {
     62             e.printStackTrace();
     63         }
     64     }
     65 
     66     public void disconnect() {
     67         try {
     68             dos.close();
     69             s.close();
     70         } catch (Exception e) {
     71             e.printStackTrace();
     72         }
     73     }
     74 
     75     // 建立私有的监听器类,TextField监听:将TextField内容放置到TextArea
     76     private class TFListener implements ActionListener {
     77 
     78         @Override
     79         public void actionPerformed(ActionEvent e) {
     80             // 获得输入框的内容,并去除两端的空格
     81             String string = tfTxt.getText().trim();
     82             // 将获取的输入内容放置到TextArea中
     83             taContent.setText(string);
     84             // 每次输入结束,将输入框置空
     85             tfTxt.setText("");
     86             try {
     87                 System.out.println(s);
     88                 // 不同每次都获取一次连接
     89                 // DataOutputStream dos=new
     90                 // DataOutputStream(s.getOutputStream());
     91                 dos.writeUTF(string);
     92                 dos.flush();
     93                 // dos.close();
     94             } catch (IOException e1) {
     95                 e1.printStackTrace();
     96             }
     97 
     98         }
     99     }
    100 }
    View Code

    Server

      1 import java.io.DataInputStream;
      2 import java.io.DataOutputStream;
      3 import java.io.EOFException;
      4 import java.io.IOException;
      5 import java.net.*;
      6 import java.security.Principal;
      7 import java.util.ArrayList;
      8 import java.util.List;
      9 
     10 //server端
     11 public class ChatServer {
     12 
     13     boolean started = false;
     14     ServerSocket ss = null;
     15     List<Client> clients = new ArrayList<Client>();
     16 
     17     public static void main(String[] args) {
     18         new ChatServer().start();
     19     }
     20 
     21     public void start() {
     22 
     23         try {
     24             // 可能会产生端口绑定异常
     25             ss = new ServerSocket(8888);
     26             // 服务器端启动以后,started=true
     27             started = true;
     28         } catch (BindException e) {
     29             System.out.println("端口使用中");
     30             System.out.println("关闭相关程序,并重新运行");
     31             System.exit(0);
     32         } catch (IOException e) {
     33             e.printStackTrace();
     34         }
     35         try {
     36             // 服务器端启动以后才能不断接收客户端的连接
     37             while (started) {
     38                 Socket s = ss.accept();
     39                 // 不能在静态方法里new一个动态的类
     40                 Client c = new Client(s);
     41                 System.out.println("a clint connected");
     42                 new Thread(c).start();
     43                 clients.add(c);
     44             }
     45             // 如果是因为客户端的关闭而导致的连接中断,则做这样的处理
     46         } catch (IOException e) {
     47             e.printStackTrace();
     48 
     49         } finally {
     50             try {
     51                 ss.close();
     52             } catch (IOException e) {
     53                 e.printStackTrace();
     54             }
     55         }
     56     }
     57 
     58 class Client implements Runnable {
     59     private Socket s;
     60     private DataInputStream dis = null;
     61     private DataOutputStream dos = null;
     62     private boolean bConnected = false;
     63 
     64     public Client(Socket s) {
     65         this.s = s;
     66         try {
     67             dis = new DataInputStream(s.getInputStream());
     68             dos = new DataOutputStream(s.getOutputStream());
     69             bConnected = true;
     70         } catch (IOException e) {
     71             e.printStackTrace();
     72 
     73         }
     74     }
     75 
     76     // 发送的方法
     77     public void send(String str) {
     78         try {
     79             dos.writeUTF(str);
     80         } catch (IOException e) {
     81             e.printStackTrace();
     82         }
     83     }
     84 
     85     @Override
     86     public void run() {
     87         try {
     88             while (bConnected) {
     89                 String str = dis.readUTF();
     90                 System.out.println(str);
     91                 for(int i=0;i<clients.size();i++){
     92                     Client c=clients.get(i);
     93                     c.send(str);
     94                 }
     95             }
     96         } catch (EOFException e) {
     97             System.out.println("Client closed");
     98         } catch (IOException e) {
     99             e.printStackTrace();
    100         } finally {
    101             try {
    102                 if (dis != null) {
    103                     dis.close();
    104                 }
    105                 if (s != null) {
    106                     s.close();
    107                 }
    108                 if(dos!=null){
    109                     dos.close();
    110                 }
    111             } catch (Exception e2) {
    112                 e2.printStackTrace();
    113             }
    114         }
    115 
    116     }
    117 }
    118 }
    View Code

    将每个连接上的客户端Client添加到我们的List集合中,方便我们将我们的输入内容发送到List集合保存的Client;

    版本1.2

    ChatClient

      1 import java.awt.BorderLayout;
      2 import java.awt.Frame;
      3 import java.awt.TextArea;
      4 import java.awt.TextField;
      5 import java.awt.event.ActionEvent;
      6 import java.awt.event.ActionListener;
      7 import java.awt.event.WindowAdapter;
      8 import java.awt.event.WindowEvent;
      9 import java.io.DataInputStream;
     10 import java.io.DataOutputStream;
     11 import java.io.IOException;
     12 import java.net.Socket;
     13 import java.net.SocketException;
     14 import java.net.UnknownHostException;
     15 
     16 //转发给
     17 public class ChatClient extends Frame {
     18 
     19     // 暴露Socket
     20     Socket s = null;
     21     DataOutputStream dos = null;
     22     DataInputStream dis = null;
     23     private boolean bConnected = false;
     24     TextField tfTxt = new TextField();
     25     TextArea taContent = new TextArea();
     26 
     27     Thread tRecv=new Thread(new RecvThread());
     28     public static void main(String[] args) {
     29         new ChatClient().launchFrame();
     30     }
     31 
     32     /**
     33      * Version 1.2
     34      */
     35     public void launchFrame() {
     36         // 设置Frame位置
     37         setLocation(400, 300);
     38         // 设置Frame大小
     39         this.setSize(300, 300);
     40         // 将输入框TextField加到Frame中,并放置到Frame布局的上面
     41         add(tfTxt, BorderLayout.SOUTH);
     42         // 将显示框TextArea加到Frame中,并放置到Frame布局的下面
     43         add(taContent, BorderLayout.NORTH);
     44         // 调整布局,处理多余空白框
     45         pack();
     46         // 添加窗口监听
     47         this.addWindowListener(new WindowAdapter() {
     48 
     49             @Override
     50             public void windowClosing(WindowEvent e) {
     51                 // 窗口关闭的时候释放连接资源
     52                 disconnect();
     53                 System.exit(0);
     54             }
     55         });
     56 
     57         // 将监听器类TFListener添加到输入框TextField中
     58         tfTxt.addActionListener(new TFListener());
     59         // 窗口可见
     60         setVisible(true);
     61         connect();
     62         
     63         tRecv.start();
     64     }
     65 
     66     // 建立连接的方法
     67     public void connect() {
     68         try {
     69             s = new Socket("127.0.0.1", 8888);
     70             dos = new DataOutputStream(s.getOutputStream());
     71             dis = new DataInputStream(s.getInputStream());
     72             System.out.println("connected!");
     73             bConnected = true;
     74         } catch (UnknownHostException e) {
     75             e.printStackTrace();
     76         } catch (IOException e) {
     77             e.printStackTrace();
     78         }
     79     }
     80 
     81     public void disconnect() {
     82         try {
     83             dos.close();
     84             dis.close();
     85             s.close();
     86         } catch (IOException e) {
     87             e.printStackTrace();
     88         }
     89     /*    try {
     90             bConnected=false;
     91             tRecv.join();
     92         } catch(InterruptedException e){
     93             e.printStackTrace();
     94         } finally{
     95             try {
     96                 dos.close();
     97                 dis.close();
     98                 s.close();
     99             } catch (IOException e) {
    100                 e.printStackTrace();
    101             }
    102             
    103         }*/
    104     }
    105 
    106     private class RecvThread implements Runnable {
    107 
    108         @Override
    109         public void run() {
    110             try {
    111                 while (bConnected) {
    112                     String str = dis.readUTF();
    113 //                    System.out.println(str);
    114                     taContent.setText(taContent.getText()+str+"
    ");
    115                 }
    116             }catch(SocketException e){
    117                 System.out.println("退出!over");
    118             }catch (IOException e) {
    119                 e.printStackTrace();
    120             }
    121         }
    122     }
    123 
    124     // 建立私有的监听器类,TextField监听:将TextField内容放置到TextArea
    125     private class TFListener implements ActionListener {
    126 
    127         @Override
    128         public void actionPerformed(ActionEvent e) {
    129             // 获得输入框的内容,并去除两端的空格
    130             String string = tfTxt.getText().trim();
    131             // 将获取的输入内容放置到TextArea中
    132             taContent.setText(string);
    133             // 每次输入结束,将输入框置空
    134             tfTxt.setText("");
    135             try {
    136                 System.out.println(s);
    137                 // 不同每次都获取一次连接
    138                 // DataOutputStream dos=new
    139                 // DataOutputStream(s.getOutputStream());
    140                 dos.writeUTF(string);
    141                 dos.flush();
    142                 // dos.close();
    143             } catch (IOException e1) {
    144                 e1.printStackTrace();
    145             }
    146 
    147         }
    148     }
    149 }
    View Code

    Server

      1 import java.io.DataInputStream;
      2 import java.io.DataOutputStream;
      3 import java.io.EOFException;
      4 import java.io.IOException;
      5 import java.net.BindException;
      6 import java.net.ServerSocket;
      7 import java.net.Socket;
      8 import java.util.ArrayList;
      9 import java.util.List;
     10 
     11 //server端
     12 public class ChatServer {
     13 
     14     boolean started = false;
     15     ServerSocket ss = null;
     16     List<Client> clients = new ArrayList<Client>();
     17 
     18     public static void main(String[] args) {
     19         new ChatServer().start();
     20     }
     21 
     22     public void start() {
     23 
     24         try {
     25             // 可能会产生端口绑定异常
     26             ss = new ServerSocket(8888);
     27             // 服务器端启动以后,started=true
     28             started = true;
     29         } catch (BindException e) {
     30             System.out.println("端口使用中");
     31             System.out.println("关闭相关程序,并重新运行");
     32             System.exit(0);
     33         } catch (IOException e) {
     34             e.printStackTrace();
     35         }
     36         try {
     37             // 服务器端启动以后才能不断接收客户端的连接
     38             while (started) {
     39                 Socket s = ss.accept();
     40                 // 不能在静态方法里new一个动态的类
     41                 Client c = new Client(s);
     42                 System.out.println("a clint connected");
     43                 new Thread(c).start();
     44                 clients.add(c);
     45             }
     46             // 如果是因为客户端的关闭而导致的连接中断,则做这样的处理
     47         } catch (IOException e) {
     48             e.printStackTrace();
     49 
     50         } finally {
     51             try {
     52                 ss.close();
     53             } catch (IOException e) {
     54                 e.printStackTrace();
     55             }
     56         }
     57     }
     58 
     59 class Client implements Runnable {
     60     private Socket s;
     61     private DataInputStream dis = null;
     62     private DataOutputStream dos = null;
     63     private boolean bConnected = false;
     64 
     65     public Client(Socket s) {
     66         this.s = s;
     67         try {
     68             dis = new DataInputStream(s.getInputStream());
     69             dos = new DataOutputStream(s.getOutputStream());
     70             bConnected = true;
     71         } catch (IOException e) {
     72             e.printStackTrace();
     73 
     74         }
     75     }
     76 
     77     // 发送的方法
     78     public void send(String str) {
     79         try {
     80             dos.writeUTF(str);
     81         } catch (IOException e) {
     82             e.printStackTrace();
     83         }
     84     }
     85 
     86     @Override
     87     public void run() {
     88         try {
     89             while (bConnected) {
     90                 String str = dis.readUTF();
     91                 System.out.println(str);
     92                 for(int i=0;i<clients.size();i++){
     93                     Client c=clients.get(i);
     94                     c.send(str);
     95                 }
     96             }
     97         } catch (EOFException e) {
     98             System.out.println("Client closed");
     99         } catch (IOException e) {
    100             e.printStackTrace();
    101         } finally {
    102             try {
    103                 if (dis != null) {
    104                     dis.close();
    105                 }
    106                 if (s != null) {
    107                     s.close();
    108                 }
    109                 if(dos!=null){
    110                     dos.close();
    111                 }
    112             } catch (Exception e2) {
    113                 e2.printStackTrace();
    114             }
    115         }
    116 
    117     }
    118 }
    119 }
    View Code

    此时我们已经可以实现我们的预期功能了,不同的客户端可以进行通信了;

    版本1.3

    ChatClient

      1 import java.awt.*;
      2 import java.awt.event.*;
      3 import java.io.*;
      4 import java.net.*;
      5 
      6 public class ChatClient extends Frame {
      7     Socket s = null;
      8     DataOutputStream dos = null;
      9     DataInputStream dis = null;
     10     private boolean bConnected = false;
     11 
     12     TextField tfTxt = new TextField();
     13 
     14     TextArea taContent = new TextArea();
     15 
     16     Thread tRecv = new Thread(new RecvThread());
     17 
     18     public static void main(String[] args) {
     19         new ChatClient().launchFrame();
     20     }
     21 
     22     public void launchFrame() {
     23         setLocation(400, 300);
     24         this.setSize(300, 300);
     25         add(tfTxt, BorderLayout.SOUTH);
     26         add(taContent, BorderLayout.NORTH);
     27         pack();
     28         this.addWindowListener(new WindowAdapter() {
     29 
     30             @Override
     31             public void windowClosing(WindowEvent arg0) {
     32                 disconnect();
     33                 System.exit(0);
     34             }
     35 
     36         });
     37         tfTxt.addActionListener(new TFListener());
     38         setVisible(true);
     39         connect();
     40 
     41         tRecv.start();
     42     }
     43 
     44     public void connect() {
     45         try {
     46             s = new Socket("127.0.0.1", 8888);
     47             dos = new DataOutputStream(s.getOutputStream());
     48             dis = new DataInputStream(s.getInputStream());
     49             System.out.println("connected!");
     50             bConnected = true;
     51         } catch (UnknownHostException e) {
     52             e.printStackTrace();
     53         } catch (IOException e) {
     54             e.printStackTrace();
     55         }
     56 
     57     }
     58 
     59     public void disconnect() {
     60         try {
     61             dos.close();
     62             dis.close();
     63             s.close();
     64         } catch (IOException e) {
     65             e.printStackTrace();
     66         }
     67 
     68         /*
     69          * try { bConnected = false; tRecv.join(); } catch(InterruptedException
     70          * e) { e.printStackTrace(); } finally { try { dos.close(); dis.close();
     71          * s.close(); } catch (IOException e) { e.printStackTrace(); } }
     72          */
     73     }
     74 
     75     private class TFListener implements ActionListener {
     76 
     77         public void actionPerformed(ActionEvent e) {
     78             String str = tfTxt.getText().trim();
     79             // taContent.setText(str);
     80             tfTxt.setText("");
     81 
     82             try {
     83                 // System.out.println(s);
     84                 dos.writeUTF(str);
     85                 dos.flush();
     86                 // dos.close();
     87             } catch (IOException e1) {
     88                 e1.printStackTrace();
     89             }
     90 
     91         }
     92 
     93     }
     94 
     95     private class RecvThread implements Runnable {
     96 
     97         public void run() {
     98             try {
     99                 while (bConnected) {
    100                     String str = dis.readUTF();
    101                     // System.out.println(str);
    102                     taContent.setText(taContent.getText() + str + '
    ');
    103                 }
    104             } catch (SocketException e) {
    105                 System.out.println("退出了,bye!");
    106             } catch (EOFException e) {
    107                 System.out.println("推出了,bye - bye!");
    108             } catch (IOException e) {
    109                 e.printStackTrace();
    110             }
    111 
    112         }
    113 
    114     }
    115 }
    View Code

    Server

      1 import java.io.*;
      2 import java.net.*;
      3 import java.util.*;
      4 
      5 public class ChatServer {
      6     boolean started = false;
      7     ServerSocket ss = null;
      8 
      9     List<Client> clients = new ArrayList<Client>();
     10 
     11     public static void main(String[] args) {
     12         new ChatServer().start();
     13     }
     14 
     15     public void start() {
     16         try {
     17             ss = new ServerSocket(8888);
     18             started = true;
     19         } catch (BindException e) {
     20             System.out.println("端口使用中....");
     21             System.out.println("请关掉相关程序并重新运行服务器!");
     22             System.exit(0);
     23         } catch (IOException e) {
     24             e.printStackTrace();
     25         }
     26 
     27         try {
     28 
     29             while (started) {
     30                 Socket s = ss.accept();
     31                 Client c = new Client(s);
     32                 System.out.println("a client connected!");
     33                 new Thread(c).start();
     34                 clients.add(c);
     35                 // dis.close();
     36             }
     37         } catch (IOException e) {
     38             e.printStackTrace();
     39         } finally {
     40             try {
     41                 ss.close();
     42             } catch (IOException e) {
     43                 // TODO Auto-generated catch block
     44                 e.printStackTrace();
     45             }
     46         }
     47     }
     48 
     49     class Client implements Runnable {
     50         private Socket s;
     51         private DataInputStream dis = null;
     52         private DataOutputStream dos = null;
     53         private boolean bConnected = false;
     54 
     55         public Client(Socket s) {
     56             this.s = s;
     57             try {
     58                 dis = new DataInputStream(s.getInputStream());
     59                 dos = new DataOutputStream(s.getOutputStream());
     60                 bConnected = true;
     61             } catch (IOException e) {
     62                 e.printStackTrace();
     63             }
     64         }
     65 
     66         public void send(String str) {
     67             try {
     68                 dos.writeUTF(str);
     69             } catch (IOException e) {
     70                 clients.remove(this);
     71                 System.out.println("对方退出了!我从List里面去掉了!");
     72                 // e.printStackTrace();
     73             }
     74         }
     75 
     76         public void run() {
     77             try {
     78                 while (bConnected) {
     79                     String str = dis.readUTF();
     80                     System.out.println(str);
     81                     for (int i = 0; i < clients.size(); i++) {
     82                         Client c = clients.get(i);
     83                         c.send(str);
     84                         // System.out.println(" a string send !");
     85                     }
     86                     /*
     87                      * for(Iterator<Client> it = clients.iterator();
     88                      * it.hasNext(); ) { Client c = it.next(); c.send(str); }
     89                      */
     90                     /*
     91                      * Iterator<Client> it = clients.iterator();
     92                      * while(it.hasNext()) { Client c = it.next(); c.send(str);
     93                      * }
     94                      */
     95                 }
     96             } catch (EOFException e) {
     97                 System.out.println("Client closed!");
     98             } catch (IOException e) {
     99                 e.printStackTrace();
    100             } finally {
    101                 try {
    102                     if (dis != null)
    103                         dis.close();
    104                     if (dos != null)
    105                         dos.close();
    106                     if (s != null) {
    107                         s.close();
    108                         // s = null;
    109                     }
    110 
    111                 } catch (IOException e1) {
    112                     e1.printStackTrace();
    113                 }
    114 
    115             }
    116         }
    117 
    118     }
    119 }
    View Code

    对程序出现的一些bug进行了修复,细化了关闭连接资源等操作,可以根据每个版本的差异梳理清楚代码的编写过程;

  • 相关阅读:
    JavaScipt
    实例应用,做了一个网页
    css 层叠式样式表(3)
    css 层叠式样式表(2)
    css 层叠式样式表(1)
    HTML 框架
    .NET回归 HTML----表单元素(1)和一些常用的标记
    .NET回归 HTML----超文本标记语言(暂时无图)
    排序算法: 选择排序法
    排序算法:快速排序法
  • 原文地址:https://www.cnblogs.com/ysw-go/p/5499630.html
Copyright © 2020-2023  润新知