• java自己写的简单聊天工具SimpleQQ感悟


    Demo如下:

    客户端:

    /*
     * 一个简单的QQ
     * 2013-8-1
     * @李志杰
     */
    package SimpleQQ_Client;
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.io.*;
    import java.net.*;
    
    public class DemoQQ_Client
    {
        public static void main(String[] args)
        {
            // TODO Auto-generated method stub
            DemoQQ_Client demoQQ_Server_1 = new DemoQQ_Client();
        }
        public DemoQQ_Client()
        {
            
            //初始化界面,开始界面的多线程
            MyPanel mp;        
            mp = new MyPanel();
            
            Thread t1 = new Thread(mp);
            t1.start();
            
            //服务器getter
            MyClient mServer = new MyClient();
            Thread t2 = new Thread(mServer);
            t2.start();
            
            //服务器sender
            MyClient_writer myClient_writer = new MyClient_writer();
            Thread t3 = new Thread(myClient_writer);
            t3.start();
            
            /*
            //测试线程
            Mytest mytest = new Mytest();
            Thread t4 = new Thread(mytest);
            t4.start();
            */
        }
    }
    
    //共享参数类
    class MyBaseClient
    {
        //定义参数,务必让发送信息和接收信息的参数共享
        static Socket s;
        static String send_ino,get_ino;
    
    }
    
    class MyClient_writer extends MyBaseClient implements Runnable //QQ写者
    {
    
        @Override
        public void run()
        {
            // TODO Auto-generated method stub
            while(true)
            {
                try
                {
                    Thread.sleep(500);
                }
                catch (InterruptedException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                sendIno();
                send_ino = null;
            }
        }
        //发送信息
            public void sendIno()
            {
                if(send_ino == null)
                {
                    return;
                }
                try
                {
                    //发送数据
                    PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
                    //获取发送内容
                    pw.println(send_ino);
                    send_ino = "Client :" + send_ino +"
    ";
                    
                }
                catch (IOException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
    }
    
    class MyClient extends MyBaseClient implements Runnable
    {        
        public MyClient()
        {
            //下面是主要功能
            try
            {
                s = new Socket("127.0.0.1", 9999);
                get_ino = "欢迎使用星尘QQ简易版
    ";
            }
            catch (IOException e)
            {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            }        
        }
    
        //传递返回信息
        public void getIno()
        {
            try
            {
                //读数据
                InputStreamReader inr = new InputStreamReader(s.getInputStream());
                BufferedReader bf = new BufferedReader(inr);
                get_ino = "Server :"+bf.readLine()+"
    ";
            }
            catch (IOException e)
            {
                System.out.println("Error!");
                return;
            }
        }
        
        @Override
        public void run()
        {
            // TODO Auto-generated method stub
            while(true)
            {
                try
                {
                    Thread.sleep(500);
                }
                catch (InterruptedException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
    
                getIno();
    
            }
        }
    }
    
    
    //专门的界面类,以后要用这种方式去画界面,不要用视频教程里面的
    class MyPanel extends JFrame implements Runnable,ActionListener
    {
        
        //定义参数
        String sender,getter;
        MyBaseClient mbc = new MyBaseClient();
        //定义组件
        JPanel jp;
        JTextArea jta;
        JButton jb;
        JTextField jt;
        JScrollPane jsp;
        
        public MyPanel()
        {
            
    
            //创建组件
            jp = new JPanel();
            jta = new JTextArea();
            jb = new JButton("发送");
            jt = new JTextField();
            jsp = new JScrollPane(jta);
            
            jt.setCaretColor(Color.GREEN);//jt绿色光标
            jt.setForeground(Color.GREEN);//jt绿色字体
            
            //信息区只能读
            jta.setEditable(false);
            //添加监听
            jb.setActionCommand("send");
            //注册监听
            jb.addActionListener(this);
            
            //添加组件
            jp.setLayout(new GridLayout(2,1));
            
            jp.add(jt);
            jp.add(jb);
            
            this.setLayout(new GridLayout(2,1));
            this.add(jsp);
            this.add(jp);
            
            this.setSize(400,400);
            this.setVisible(true);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setTitle("QQ_Client");
            
        
        }
        public void paint(Graphics g)
        {
            super.paint(g);
        }
        @Override
    public void run()
    {
        while(true)
        {
            try
            {
                Thread.sleep(500);
               
            }
            catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            sender = this.jt.getText();
            getter = mbc.get_ino;
            //更新面板
            if(getter == null) //信息为空,跳过更新
            {
                continue;
            }
            if(mbc.get_ino != null)
            {
                String s_board = this.jta.getText() + getter;        //通过面板来获取记录
                this.jta.setText(s_board);
                mbc.get_ino = null;
            }
            this.repaint();    
        }
    }
        @Override
      public void actionPerformed(ActionEvent e)
      {
            if(e.getActionCommand() == "send")
            {
                //发送信息
                mbc.send_ino = sender;        //更新消息缓存
                String s_board = this.jta.getText() + "Client :" +sender +"
    ";        //通过面板来获取记录
                this.jta.setText(s_board);
                jt.setText(null);//清空内容
                this.repaint();    
            }
      }
    }
    
    
    //测试类
    class Mytest extends MyBaseClient implements Runnable
    {
    
        int times = 0;
      public void run()
      {
            // TODO Auto-generated method stub
            try
          {
                while(true)
                {
                    times++;
                    Thread.sleep(100);
                    System.out.println("Time :"+ times + " " + get_ino);
                }
          }
          catch (Exception e)
          {
                // TODO: handle exception
          }
      }
        
    }

    服务器端的:

    /*
     * 一个简单的QQ
     * 2013-8-1
     * @李志杰
     */
    package SimpleQQ_Server;
    import java.awt.*;
    import java.awt.event.*;
    
    import javax.swing.*;
    
    import java.io.*;
    import java.net.*;
    
    public class DemoQQ_Server
    {
        public static void main(String[] args)
        {
            // TODO Auto-generated method stub
            DemoQQ_Server demoQQ_Server = new DemoQQ_Server();
        }
        public DemoQQ_Server()
        {
            
            //初始化界面,开始界面的多线程
            MyPanel mp;        
            mp = new MyPanel();
            
            Thread t1 = new Thread(mp);
            t1.start();
            
            //服务器getter
            MyServer mServer = new MyServer();
            Thread t2 = new Thread(mServer);
            t2.start();
            
            //服务器sender
            MyServer_writer myClient_writer = new MyServer_writer();
            Thread t3 = new Thread(myClient_writer);
            t3.start();
            
        }
    }
    
    //共享参数类
    class MyBaseServer
    {
        //定义参数,务必让发送信息和接收信息的参数共享
        static Socket s;
        static ServerSocket ss;
        static String send_ino,get_ino;
    }
    
    class MyServer_writer extends MyBaseServer implements Runnable //QQ写者
    {
    
        @Override
        public void run()
        {
            // TODO Auto-generated method stub
            while(true)
            {
                try
                {
                    Thread.sleep(500);
                }
                catch (InterruptedException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                sendIno();
                send_ino = null;
                //get_ino = null;
            }
        }
        //发送信息
            public void sendIno()
            {
                if(send_ino == null)
                {
                    return;
                }
                try
                {
                    //发送数据
                    PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
                    //获取发送内容
                    pw.println(send_ino);
                    send_ino = "Client :" + send_ino +"
    ";
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
    }
    
    class MyServer extends MyBaseServer implements Runnable
    {        
        public MyServer()
        {
            //下面是主要功能
            try
            {
                get_ino = "欢迎使用星尘QQ简易版
    ";
                ss = new ServerSocket(9999);
                s = ss.accept();
            }
            catch (IOException e)
            {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            }        
        }
    
        //传递返回信息
        public void getIno()
        {
            //要拥有一个判断去跳出这个读取,否则一旦进入try块,如果没有信息进来,读者会一直占用cpu而不会进入到写者,除非写者也开多线程
            /*
            if(get_ino == null)
            {
                return;
            }
            */
            try
            {
                //读数据
                InputStreamReader inr = new InputStreamReader(s.getInputStream());
                BufferedReader bf = new BufferedReader(inr);
                get_ino = "Server :"+bf.readLine()+"
    ";
            }
            catch (IOException e)
            {
                return;
            }
        }
        
        @Override
        public void run()
        {
            // TODO Auto-generated method stub
            while(true)
            {
                try
                {
                    Thread.sleep(500);
                }
                catch (InterruptedException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                getIno();
                //sendIno();
               // send_ino = null;
                //get_ino = null;
            }
        }
    }
    
    
    //专门的界面类,以后要用这种方式去画界面,不要用视频教程里面的
    class MyPanel extends JFrame implements Runnable,ActionListener
    {
        
        //定义参数
        String sender,getter;
        MyBaseServer mbs = new MyBaseServer();
        //定义组件
        JPanel jp;
        JTextArea jta;
        JButton jb;
        JTextField jt;
        JScrollPane jsp;
        
        public MyPanel()
        {
            
    
            //创建组件
            jp = new JPanel();
            jta = new JTextArea();
            jb = new JButton("发送");
            jt = new JTextField();
            jsp = new JScrollPane(jta);
            
            jt.setCaretColor(Color.RED);//jt红色光标
            jt.setForeground(Color.RED);//jt红色字体
            
            //信息区只能读
            jta.setEditable(false);
            //添加监听
            jb.setActionCommand("send");
            
            
            //注册监听
            jb.addActionListener(this);
            
            //添加组件
            jp.setLayout(new GridLayout(2,1));
            
            jp.add(jt);
            jp.add(jb);
            
            this.setLayout(new GridLayout(2,1));
            this.add(jsp);
            this.add(jp);
            
            this.setSize(400,400);
            this.setVisible(true);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setTitle("QQ_Server");
            
        
        }
        public void paint(Graphics g)
        {
            super.paint(g);
        }
        @Override
    public void run()
    {
        while(true)
        {
            try
            {
                Thread.sleep(500);
               
            }
            catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            sender = this.jt.getText();
            getter = mbs.get_ino;
            //更新面板
            //更新面板
            if(getter == null) //信息为空,跳过更新
            {
                continue;
            }
            if(mbs.get_ino != null)
            {
                String s_board = this.jta.getText() + getter;        //通过面板来获取记录
                this.jta.setText(s_board);
                mbs.get_ino = null;
            }
            this.repaint();    
        }
    }
        @Override
      public void actionPerformed(ActionEvent e)
      {
            if(e.getActionCommand() == "send")
            {
                //发送信息
                mbs.send_ino = sender;        //更新消息缓存
                String s_board = this.jta.getText() + "Client :" +sender +"
    ";        //通过面板来获取记录
                this.jta.setText(s_board);
                jt.setText(null);//清空内容
                this.repaint();    
            }
      }
    }

    总结:

      先说一下这个简单项目的设计思路:

      1、本着模块独立化的思路,将整个项目的两个模块(界面+通讯)独立成三个类,其中界面类为MyPanel,通讯(这里以客户端为例)为MyClient(接收消息)和MyClient_writer(发送消息)。

      2、除了以上三个类外,还设计了一个共享信息的类,即MyBaseClient,通讯的两个类直接继承这个类,界面类通过将这个类实例化来共享这个类的变量信息;

      3、此项目还有一个特色的地方是,使用了三个线程,一个是界面线程用以定时绘图和监听按钮,另一个是接收消息的类,用以定时接收消息。除了这两个外,还有一个用以发送消息。之所以要这样设计,首先是要让界面与后台逻辑分离,即界面与通讯分离,其次是要让后台中的读写分离,实现同步和实时。

      这是我今天的技术收获,记此。

  • 相关阅读:
    tempfile 模块
    gc 模块
    hashlib 加密模块
    optparse模块
    ios网络相关问题-HTTPS与网络安全
    Charles抓包原理
    ios网络相关问题-HTTP特点
    ios网络相关问题-HTTP协议
    React-Native package.json、node_modules等文件说明
    Swift 4.0 中的 open,public,internal,fileprivate,private
  • 原文地址:https://www.cnblogs.com/starwolf/p/3231523.html
Copyright © 2020-2023  润新知