昨天回忆了一下以前做的一个实时的群聊小程序。用JAVA写得。开发步骤如下:

这是面向过程的开发。

第一步,建立服务器端。

第二步,建立客户端并连接服务端。

第三步,客户端发送消息服务器端能接收到。

第四步,实现多客户连接服务端,并能接收多客户端发来的消息。可以采用多线程和异步的方法解决服务端被占用的情况。

第五步,服务端转发客户端发送的信息到每一个客户端。

第六步,消除小Bug。

ChatServer.java

import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.EOFException;import java.util.*;import java.io.IOException;import java.net.BindException;import java.net.ServerSocket;import java.net.Socket;import java.net.SocketException;public class ChatServer{    boolean started = false;    ServerSocket ss = null;                              List
clients = new ArrayList
(); public static void main(String[] args) { new ChatServer().start(); } public void start(){ try { ss = new ServerSocket(8881); } catch (BindException e){ System.out.println("端口已被占用!"); System.out.println("请结束相关进程!"); System.exit(0); } catch (Exception e) { e.printStackTrace(); } try{ started = true; while (started) { Socket s = ss.accept(); //阻塞性函数,不断接收客户端连接 Client c = new Client(s);//不能再静态main()里面new一个动态的方法,故将启动过程包装成一个public函数System.out.println("a client connected"); new Thread(c).start(); clients.add(c); } } catch (Exception e) { e.printStackTrace(); }finally{ try { ss.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class Client implements Runnable{//区分客户端,用一个线程操作一个客户端,也可以采用异步的方法。这里用线程,比较占资源。等我写出异步的方法后再共享。 private Socket s= null; private DataInputStream dis= null; private DataOutputStream dos=null; private boolean bConnected = false; public Client(Socket s){ this.s= s; try { dis=new DataInputStream(s.getInputStream()); dos=new DataOutputStream(s.getOutputStream()); bConnected = true; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void send(String str){ // try { dos.writeUTF(str); } catch (IOException e) { // TODO Auto-generated catch block clients.remove(this); System.out.println("一个客户退出了!List已去除"); //e.printStackTrace(); } } public void run() { try { while (bConnected) { String str; str = dis.readUTF();// 阻塞性函数,会一直占用线程资源System.out.println(str); for (int i = 0; i < clients.size(); i++) { Client c = clients.get(i); c.send(str); } } } catch (EOFException e){ System.out.println("一个客户已退出!"); }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(dis!=null) try { dis.close(); if (dos != null) dos.close(); if (s != null) s.close(); } catch (SocketException e) { clients.remove(this); System.out.println("一个客户已退出!"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }}

ChatClient.java

import java.awt.BorderLayout;import java.awt.Frame;import java.awt.TextArea;import java.awt.TextField;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.EOFException;import java.io.IOException;import java.net.Socket;import java.net.SocketException;import java.net.UnknownHostException;                                      public class ChatClient extends Frame{    Socket s = null;    DataOutputStream dos = null;    DataInputStream dis = null;    private boolean bConnected=false;    TextField tfTxt = new TextField();//输入框    TextArea taContent = new TextArea();//显示聊天信息框                                                                                      public static void main(String[] args)    {        new ChatClient().lanunchFrame();    }                                             public void lanunchFrame(){        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 TexFileListener());        setVisible(true);        connect();                                                     new Thread(new RecvThread()).start();    }                                             public void connect(){        try        {            s= new Socket("127.0.0.1",8881);            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 (Exception e1)        {            e1.printStackTrace();        }        /*try        {            bConnected = false;  //保证            recvThread.join();        }        catch (InterruptedException e){            e.printStackTrace();        }        finally{            try            {                dos.close();                dis.close();                s.close();            } catch (IOException e)            {                // TODO Auto-generated catch block                e.printStackTrace();            }        }*/    }                                             private class TexFileListener implements ActionListener{        public void actionPerformed(ActionEvent e)        {            String str=tfTxt.getText().trim();            //taContent.setText(str);            tfTxt.setText("");            try            {                dos.writeUTF(str);                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+'\n');                }            }            catch (SocketException e){                System.out.println("已退出!");            }            catch (EOFException e){                System.out.println("已退出!");            }            catch (IOException e)            {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }}