java简易聊天室1.2

系统正在退出

先通知服务器,让服务器该做什么做什么。

停掉线程,监听等一段时间,时间到cut掉

SERVER端

import java.net.*;
import java.io.*;
import java.util.*;
public class Chatserver {

    boolean started=false;//有没有监听好
    ServerSocket ss=null;//初始化
    List<Client>clients=new ArrayList<Client>();
    
    public static void main(String[] args) {
         new Chatserver().start();
    }
        
    public void start()
    {
        try {
            ss=new ServerSocket(8888);//端口号8888,TCP,监听在8888端口
            started=true;//连接上
        }catch (BindException e){
            System.out.println("端口使用中");
            System.exit(0);
        }catch(IOException e){
            e.printStackTrace();//给出方法的调用程序,一直到异常的产生位置    
        }
        try{
            
            while(started)//已经启动
            {
                Socket s=ss.accept();//已经启动不断接收客户端的连接
                Client c=new Client(s);//接收进来以后起一个线程
                System.out.println("a client connected!");
                new Thread(c).start();//让这个线程启动,为它服务
                clients.add(c);
              //dis.close();
                }
                
            }catch (IOException e) {
            e.printStackTrace();
            }finally{
                try
                {
                    ss.close();
                }catch(IOException e){
                    e.printStackTrace();
                    }
            }

    }
    

    class Client implements Runnable{//线程内部类
        
        private Socket s;//包装的每个客户端一个单独的Socket,一个半连接
        private DataInputStream dis=null;//每个客户端都保有自己的inputStream;从Socket里面赌内容的输入管道
        //保留有自己的连接
        private DataOutputStream dos=null;
        private boolean bConnected=false;//是否连上,初始化false
        public Client(Socket s){//传递Socket这个属性,构造函数
            this.s=s;//初始化
            try {
                dis=new DataInputStream(s.getInputStream());//初始化
                dos=new DataOutputStream(s.getOutputStream());
                 bConnected=true;//连上以后等于TRUE
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        public void send(String str){
             try {
                dos.writeUTF(str);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
            
        public void run(){//单独的线程为单独的客户端服务
            //接收到对方之后变成true
            try{
              while(bConnected){//有东西来就读
                String str=dis.readUTF();//阻塞式,接受客户端给我的字符串且打印
                System.out.println(str);
               
                for(int i=0;i<clients.size();i++){//集合类
                    Client c=clients.get(i);
                    c.send(str);
System.out.println("发出了一句话");                    
                }
                
                /*for(Iterator<Client> it=clients.iterator();it.hasNext();){
                    Client c=it.next();
                    c.send(str);
                }*/
                /* Iterator it=clients.iterator();
                while(it.hasNext()){
                    Client c=it.next();
                    c.send(str);
                                    }//内部锁定,没必要 效率低*/
               }
            }catch (EOFException e){
                System.out.println("Client closed!");
            } 
            catch (IOException e) {
                e.printStackTrace();
            }finally{
                try{
                    if(dis !=null) dis.close();
                    if(dos !=null) dos.close();
                    if(s!=null){
                        s.close();
                        //s=null;
                    }
                }catch(IOException e1){
                    e1.printStackTrace();
                }
            }            
        }
    }
}


Client

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.net.*;
import java.io.*;
public class Chatclient extends Frame{
    
    Socket s=null;
    DataOutputStream dos=null;
    DataInputStream dis=null;
    private boolean bConnected =false;
    
    TextField tfTxt=new TextField();//只有一行可以写,有一个ACTION
    TextArea taContent=new TextArea();//标签定义多行的文本输入控件
    
    Thread tRecv=new Thread(new RecvThread());

    public static void main(String[] args) {
        new Chatclient().LaunchFrame();   
    }
    
    public void LaunchFrame()
    {
        setLocation(400,300);
        this.setSize(300,300);
        add(tfTxt,BorderLayout.SOUTH);
        add(taContent,BorderLayout.NORTH);
        pack();
        this.addWindowListener(new WindowAdapter(){//关闭窗口

            @Override
            public void windowClosing(WindowEvent e) {
                disconnect();
                System.exit(0);
            }
            
        });//匿名类
        tfTxt.addActionListener(new TFListener());
        setVisible(true);
        connect();

        //new Thread(new RecvThread()).start();
        tRecv.start();
    }
    
    public void connect()
    {
        try {
            s=new Socket("127.0.0.1",8888);
            dos=new DataOutputStream(s.getOutputStream());
            dis=new DataInputStream(s.getInputStream());//初始化
            System.out.println("connected!");
            bConnected=true;
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
    
    public void disconnect()//关闭方法
    {
        try{
          dos.close();
          dis.close();
          s.close();
          }catch (IOException e){
                e.printStackTrace();
           }
        
        
        /*try{
            bConnected=false;//关闭线程
            tRecv.join();//合并        
        
        }catch(InterruptedException e){
            e.printStackTrace();
        }finally{
            try{
                    dos.close();
             dis.close();
            s.close();
        }catch (IOException e){
            e.printStackTrace();
            }
        }*/
    }
    private class TFListener implements ActionListener

    {
        public void actionPerformed(ActionEvent e) {//一敲回车
            String str=tfTxt.getText().trim();
            //taContent.setText(str);
            tfTxt.setText("");//回车之后清空
            try {
                //DataOutputStream dos=new DataOutputStream(s.getOutputStream());
                dos.writeUTF(str);//把stream输出去
                dos.flush();
                //dos.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            
        }    
        
    }//内部类
    private class RecvThread implements Runnable{
        public void run(){
            try{
              while(bConnected){
                  String str=dis.readUTF();
                  System.out.println(str);
                  taContent.setText(taContent.getText()+str+'
');
               }
            }catch (SocketException e){
                System.out.println("退出");
            }catch(IOException e){
                e.printStackTrace();
             }            
        }
    }
}