Home  >  Article  >  WeChat Applet  >  Real-time group chat applet development record

Real-time group chat applet development record

高洛峰
高洛峰Original
2017-02-10 13:31:382721browse

Yesterday I recalled a real-time group chat applet I made before. Written in JAVA. The development steps are as follows:

This is process-oriented development.

The first step is to establish the server side.

The second step is to establish the client and connect to the server.

The third step is that the client sends a message and the server can receive it.

The fourth step is to realize multiple clients connecting to the server and receive messages from multiple clients. Multi-threading and asynchronous methods can be used to solve the situation where the server is occupied.

The fifth step is that the server forwards the information sent by the client to each client.

The sixth step is to eliminate small bugs.

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<Client> clients = new ArrayList<Client>();
                           
                           
    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+&#39;\n&#39;);
                }
            }
            catch (SocketException e){
                System.out.println("已退出!");
            }
            catch (EOFException e){
                System.out.println("已退出!");
            }
            catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}


For more real-time group chat applet development records, please refer to related articles Follow PHP Chinese website!


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn