java模拟一个简单的QQ

 效果图:

java模拟一个简单的QQ

 

      

package testFour;



import java.awt.Color;

import java.awt.Dimension;

import java.awt.FontMetrics;

import java.awt.Graphics;

import java.io.ByteArrayInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.net.BindException;

import java.net.ServerSocket;

import java.util.Iterator;



import javax.imageio.ImageIO;

import javax.imageio.ImageReader;

import javax.imageio.stream.ImageInputStream;

import javax.swing.ImageIcon;

import javax.swing.JLabel;

import javax.swing.JPanel;

import javax.swing.JTextPane;

import javax.swing.text.BadLocationException;

import javax.swing.text.Document;

import javax.swing.text.SimpleAttributeSet;

import javax.swing.text.StyleConstants;



public class QQ {

    public static final int PICUTER = 1; 

    public static final int FILE = 2; 

    public static final int PARAGRAPH = 3; 

    public static final int SEND = 1; 

    public static final int RECEIVE = 2; 

    public static final int FILEX = 3;

    

    public static int getUnusedPort() throws BindException{

        int port;

        for(port = 10000 ; port <= 65535; ++port){

            ServerSocket ss = null; 

            try {

                ss = new ServerSocket(port);

            } catch (IOException e) {

                e.printStackTrace();

            }

            if(ss != null) break;

        }

        if(port > 65535)

            throw new BindException("没有可用的端口!");

        return port;

    }

    

    public synchronized static void setTextPane(JTextPane tp, byte[] bt, int len, int flag, int tag){

         ImageIcon myIcon = null;

         if(tag == SEND)

             myIcon = new ImageIcon("ff.jpg");

         else if(tag == RECEIVE)

             myIcon = new ImageIcon("gg.jpg");

         else if(tag == FILEX)

             myIcon = new ImageIcon("kk.jpg");

         

         SimpleAttributeSet set = new SimpleAttributeSet();

         Document doc = tp.getStyledDocument();

         

         if(tag == SEND || tag == RECEIVE){

              tp.setCaretPosition(doc.getLength());

              JLabel fileLabel = new JLabel("", myIcon, JLabel.CENTER);

              tp.insertComponent(fileLabel);

         }

         

         if(flag == PARAGRAPH){

             FontMetrics fm = tp.getFontMetrics(tp.getFont());

             int paneWidth = tp.getWidth();

             String text = new String(bt, 0, len);

             

             if( tag/3 == SEND ){

                 StyleConstants.setForeground(set, new Color(0,255,0));//设置文字颜色

                 StyleConstants.setFontSize(set, 15);//设置字体大小

             }

             else if( tag/3 == RECEIVE){

                 StyleConstants.setForeground(set, new Color(0,0,0));//设置文字颜色

                 StyleConstants.setFontSize(set, 15);//设置字体大小

             }

             

             try

              {

                  for(int i = 0, cnt = 0; i < text.length(); ++i){

                      if((cnt += fm.charWidth(text.charAt(i))) >= paneWidth){

                          cnt = 0;

                          doc.insertString(doc.getLength(), "\n", set);

                          continue;

                      }

                      doc.insertString(doc.getLength(), String.valueOf(text.charAt(i)), set);

                  }

                  doc.insertString(doc.getLength(), "\n", set);

                  

                  tp.setCaretPosition(doc.getLength());//最简单的设置滚动条的位置到最后输出文本的地方

                                                         //就是将JTextPane中的插入符的位置移动到文本的末端!

              }

              catch (BadLocationException e)

              {

              }

             

         } else if(flag == PICUTER) {

            

             try{

                     InputStream is = new ByteArrayInputStream(bt, 0, len);

                     ImageInputStream iis = ImageIO.createImageInputStream(is);

                     Iterator<ImageReader> itImage = ImageIO.getImageReaders(iis);

                     if(itImage.hasNext()){

                         ImageReader reader = itImage.next();

                         ImageIcon ii = new ImageIcon( bt, reader.getFormatName() );

                         tp.setCaretPosition( doc.getLength() );

                         tp.insertComponent( new PicuterPanel(ii) );

                         doc.insertString(doc.getLength(), "\n", set);

                     }

             }catch(IOException ex){

                     ex.printStackTrace();

             }catch(BadLocationException e1){

                   

             }

             

         } else if(flag == FILE) {

              try{

                  tp.setCaretPosition(doc.getLength());

                  JLabel fileLabel = new JLabel(new String(bt, 0, len), myIcon, JLabel.LEFT);

                  tp.insertComponent(fileLabel);

                  doc.insertString(doc.getLength(), "\n", set);

              }catch (BadLocationException e) {

                  e.printStackTrace();

            }

         }

    }

}



class PicuterPanel extends JPanel{

    private ImageIcon ii;

    public PicuterPanel(ImageIcon ii){

        this.ii = ii;

        setPreferredSize(new Dimension(200, 300));

        setBackground(new Color(255, 255, 255));

    }

    

    protected void paintComponent(Graphics g) {

          super.paintComponent(g);

          g.drawImage(ii.getImage(), 0, 0, 200, 300, 0, 0, ii.getIconWidth(), ii.getIconHeight(), this);

    }

}
View Code
package testFour;



import java.awt.BorderLayout;

import java.awt.Color;

import java.awt.Dialog;

import java.awt.Dimension;

import java.awt.FlowLayout;

import java.awt.Font;

import java.awt.Frame;

import java.awt.Point;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

import java.net.InetAddress;

import java.net.UnknownHostException;

import java.util.Map;

import java.util.Random;

import java.util.Set;

import java.util.TreeMap;

import java.util.TreeSet;



import javax.swing.BoxLayout;

import javax.swing.ImageIcon;

import javax.swing.JButton;

import javax.swing.JLabel;

import javax.swing.JMenuItem;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.JPopupMenu;

import javax.swing.JScrollBar;

import javax.swing.JScrollPane;

import javax.swing.JTextField;

import javax.swing.ScrollPaneConstants;







public class QQDialog extends Frame{

        private JPanel QQP = new JPanel();

        private JButton myFriend = new JButton("QQ好友>>");

        private JPanel funP = new JPanel();

        private JButton add = new JButton("添加好友");

        private JButton serach = new JButton("查询好友");

        private JPanel pp = new JPanel();

        private JPanel tmp = null;

        private final int QQPheight = 397;

        private JScrollPane jsp = new JScrollPane(QQP);

        private static Set<String>QQset;//IP的集合

        private static Map<String, QQFrame>QQmap;//IP到对通信窗口的映射

        private static Map<String, String>nameToIP;//姓名到IP的映射

        ImageIcon[] ii = new ImageIcon[3];

        

        public static Map<String, QQFrame> getMap(){

            return QQmap;

        }

        

        public static Set<String> getSet(){

            return QQset;

        }

        

        public static Map<String, String> getNameToIP(){

            return nameToIP;

        }

        

        public QQDialog(){

            

            QQset = new TreeSet<String>();

            QQmap = new TreeMap<String, QQFrame>();

            nameToIP = new TreeMap<String, String>();

            

            ii[0] = new ImageIcon("ff.jpg");

            ii[1] = new ImageIcon("gg.jpg");

            ii[2] = new ImageIcon("kk.jpg");

            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

            jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);

            jsp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

            pp.add(jsp);

            pp.setLayout(new BoxLayout(pp, BoxLayout.Y_AXIS));

            QQP.setLayout(new BoxLayout(QQP, BoxLayout.Y_AXIS));

            JPanel pmyFriend = new JPanel();

            pmyFriend.setLayout(new BorderLayout());

            pmyFriend.add(myFriend, "Center");

            pmyFriend.setPreferredSize(new Dimension(300, 20));

            add(pmyFriend);

            pp.setPreferredSize(new Dimension(300, 400));

            add(pp);

            add(funP);

            

            JLabel myself = null;

            try {

                myself = new JLabel(InetAddress.getLocalHost().getHostName() + ":" + InetAddress.getLocalHost().getHostAddress());

            } catch (UnknownHostException e) {

                e.printStackTrace();

            }

            addLabelListener(myself);

            myself.setIcon(new ImageIcon("ff.jpg"));

            

            tmp = new JPanel();

            tmp.setLayout(new FlowLayout(FlowLayout.CENTER));

            tmp.setBackground(new Color(255, 0, 255));

            tmp.setPreferredSize(new Dimension(250, 60));

            tmp.add(myself);

            QQP.add(tmp);

            funP.setLayout(new FlowLayout(FlowLayout.CENTER));

            funP.add(add);

            funP.add(serach);

            

            myFriend.addMouseListener(new MouseAdapter() {

                

                    public void mouseClicked(MouseEvent e) {//将好友面板进行收缩的效果!

                        if("QQ好友>>".equals(myFriend.getText())){

                            QQP.setVisible(false);

                            myFriend.setText("QQ好友<<");

                        }

                        else{

                            QQP.setVisible(true);

                            myFriend.setText("QQ好友>>");

                        }

                    }



            });

            

            add.addMouseListener(new MouseAdapter() {

                    public void mouseClicked(MouseEvent e) {

                        InputDialog dlg = new InputDialog();

                        if(dlg.key == InputDialog.CANCELBTN || dlg.key== 0) return;

                        Random rd = new Random();

                        int index = Math.abs(rd.nextInt()) % 3;

                        JLabel ll = new JLabel(dlg.getNameText() + ":" + dlg.getIPText(), ii[index], JLabel.LEFT);

                        QQset.add(dlg.getIPText());//将新增加的好友添加到集合中!

                        nameToIP.put(dlg.getNameText(), dlg.getIPText());

                        tmp = new JPanel();

                        tmp.setLayout(new FlowLayout(FlowLayout.CENTER));

                        tmp.setBackground(new Color(255, 0, 255));

                        

                        /*

                         *  BoxLayout布局简直是蛋疼的要命,一个面板X是BoxLayout布局,如果该面板添加一个面板Y的话

                         *  那么Y就会填充X面板!如果在添加一个面板Z, 那么Y, Z就会一起布满X面板!但是可以设置Y,Z面板

                         *  的比例! 如果X添加的是一个按钮或者标签时,还不能控制其大小.....无语了!

                         *  

                         *  下面的我的做法将标签添加到面板tmp中,然后再将tmp添加中QQP面板中!这样就可以控制标签的大小了!

                         *  再添加新的面板的时候,要设置一下之前面板的PreferredSize!保证每一个标签的距离适中!

                         *  也就是保证所有的添加的面板的高度之和 == QQP.getHeight();

                         * */

                        int cnt = QQP.getComponentCount();//显示QQ好友的个数!

                        if(cnt >= 1)

                            QQP.getComponent(cnt-1).setPreferredSize(new Dimension(250, 60));

                        int h = QQP.getHeight() - cnt*60;

                        if(h < 0) h=60;

                        tmp.setPreferredSize(new Dimension(250, h));

                        tmp.add(ll);

                        QQP.add(tmp);

                        QQP.add(tmp);

                        addLabelListener(ll);//给标签添加监听器

                        JScrollBar jsb = jsp.getVerticalScrollBar();

                        QQP.updateUI();//利用当前外观的值重置 UI 属性。 也可以保证滚动条随时的更新

                        //终于搞好了,将垂直滚动条自动的移动到最低端

                        jsp.getViewport().setViewPosition(new Point(0, jsp.getVerticalScrollBar().getMaximum()));

                    }

            });

            

            serach.addMouseListener(new MouseAdapter() {

                    public void mouseClicked(MouseEvent e) {

                          String name = JOptionPane.showInputDialog(null, "好友姓名", "好友查询", JOptionPane.OK_OPTION);

                          if(name == null)  return ;

                          

                          String ip = nameToIP.get(name);

                          

                          if(ip == null)

                                  JOptionPane.showMessageDialog(null, "好友不存在!", "查询结果", JOptionPane.OK_OPTION);

                          else{

                              QQFrame fm = QQmap.get(ip);

                              if(fm == null){

                                  try{

                                         String[] ipStr = ip.split("\\.");//将字符串中的数字分离

                                         byte[] ipBuf = new byte[4];//存储IP的byte数组

                                         for(int i = 0; i < 4; i++){

                                             ipBuf[i] = (byte)(Integer.parseInt(ipStr[i])&0xff);

                                         }

                                         fm = new QQFrame(name, ipBuf);

                                    }catch(RuntimeException ex){

                                         JOptionPane.showMessageDialog(null, ex.getMessage(), "Socket错误!", JOptionPane.OK_CANCEL_OPTION);

                                         return ;

                                    }

                                  QQmap.put(ip, fm);

                              }

                              else fm.requestFocus();

                          }

                    }

            });

            

            addWindowListener(new WindowAdapter() {

                    public void windowClosing(WindowEvent e) {

                        if(qr == null) System.out.println("hehe");

                        qr.setFlag();//udp服务线程停止

                        ss.setFlag();//tcp服务线程停止

                        System.exit(0);

                    }

            });

            

            QQP.setBackground(new Color(255, 0, 255));

            funP.setBackground(new Color(255, 255, 0));

            setResizable(false);

            setSize(300, 500);

            setLocation(500, 200);

            setVisible(true);

        }

        

        

        public void addLabelListener(final JLabel lab){

             lab.setOpaque(true);

             lab.setBackground(new Color(255, 255, 255));

             lab.setPreferredSize(new Dimension(250, 55));

             

             String NameAndIP = lab.getText();

              String name = NameAndIP.substring(0, NameAndIP.indexOf(':'));

              String ip = NameAndIP.substring(NameAndIP.indexOf(':') + 1, NameAndIP.length());

            

             nameToIP.put(name, ip);

             QQset.add(ip);

             

             lab.addMouseListener(new MouseAdapter() {

                     Color oldC = lab.getBackground();

                     public void mouseEntered(MouseEvent e) {

                          lab.setBackground(new Color(0, 255, 0));

                     }

                     

                     public void mouseExited(MouseEvent e) {

                          lab.setBackground(oldC);

                     }

                     

                     public void mouseClicked(MouseEvent e) {

                          //打开通信窗口

                          if(e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2){

                                 String NameAndIP = lab.getText();

                                 String name = NameAndIP.substring(0, NameAndIP.indexOf(':'));

                                 if(QQmap.get(nameToIP.get(name)) != null){//这个好友的窗口已经存在!

                                    QQmap.get(nameToIP.get(name)).requestFocus();

                                    return ;

                                 }

                                 QQFrame fm = null;

                                try{

                                     String[] ipStr = nameToIP.get(name).split("\\.");//将字符串中的数字分离

                                     byte[] ipBuf = new byte[4];//存储IP的byte数组

                                     for(int i = 0; i < 4; i++){

                                         ipBuf[i] = (byte)(Integer.parseInt(ipStr[i])&0xff);

                                     }

                                     fm = new QQFrame(name, ipBuf);

                                     QQmap.put(nameToIP.get(name), fm);//name 和 窗口的映射!

                                }catch(RuntimeException ex){

                                    JOptionPane.showMessageDialog(null, ex.getMessage(), "错误提示!", JOptionPane.OK_CANCEL_OPTION);

                                    return ;

                                }

                          }

                          else if(e.getButton() == MouseEvent.BUTTON3){

                               JPopupMenu pm = new JPopupMenu("胡峻峥");

                               JMenuItem del = new JMenuItem("删除");

                               del.setFont(new Font("华文行楷", Font.ITALIC, 20));

                               del.setForeground(new Color(255, 0, 0));

                               del.addActionListener(new ActionListener() {

                                    public void actionPerformed(ActionEvent e) {

                                        int choose = JOptionPane.showConfirmDialog(null, "确定删除!", "删除对话框", JOptionPane.YES_NO_OPTION);

                                           if(choose == JOptionPane.OK_OPTION){

                                               QQP.remove(lab.getParent());

                                               int cnt = QQP.getComponentCount();

                                               int h = QQP.getHeight() - (cnt-1)*60;

                                             if(h < 0) h=60;

                                               if(cnt >= 1)

                                                 QQP.getComponent(cnt-1).setPreferredSize(new Dimension(250, h));

                                               

                                               cnt = QQP.getComponentCount();

                                               if(cnt*60 <= QQPheight)

                                                   QQP.setPreferredSize(new Dimension(QQP.getWidth(), QQPheight));

                                               else 

                                                   QQP.setPreferredSize(new Dimension(QQP.getWidth(), cnt*60));

                                               QQP.updateUI();

                                               

                                               String NameAndIP = lab.getText();

                                              String ip = NameAndIP.substring(NameAndIP.indexOf(':') + 1);

                                               QQset.remove(ip);

                                               QQFrame fm = QQmap.get(ip);

                                               if(fm != null) fm.dispose();

                                               nameToIP.remove(NameAndIP.substring(0, NameAndIP.indexOf(':')));

                                               QQmap.remove(ip);

                                           }

                                    }

                              });

                               

                               JMenuItem edit = new JMenuItem("编辑");

                               edit.addActionListener(new ActionListener() {

                                

                                  public void actionPerformed(ActionEvent e) {

                                        //得到之前的数据!

                                        String content = lab.getText();

                                        String oldName = content.substring(0, content.indexOf(':'));

                                        String oldIP = content.substring(content.indexOf(':')+1);

                                        //从新设置到文本框中

                                        InputDialog id = new InputDialog(oldIP, oldName, true);

                                        if(id.key == InputDialog.CANCELBTN || id.key== 0) return;

                                        lab.setText(id.NAME + ":" + id.IP);

                                        

                                        QQFrame fm = QQmap.get(oldIP);

                                        if(fm != null){

                                            try{

                                                fm.setSendIAD(id.IP);

                                                

                                                QQmap.put(id.IP, fm);

                                                fm.setTitle(id.NAME);

                                                QQmap.remove(oldIP);

                                                QQset.remove(oldIP);

                                                QQset.add(id.IP);

                                                nameToIP.remove(oldName);

                                                nameToIP.put(id.NAME, id.IP);

                                                

                                            }catch(RuntimeException ex){

                                                JOptionPane.showMessageDialog(null, ex.getMessage(), "修改之后的IP!", JOptionPane.OK_OPTION);

                                            }

                                        }

                                    }

                              });

                               edit.setFont(new Font("华文行楷", Font.ITALIC, 20));

                               edit.setForeground(new Color(255, 0, 255));

                               pm.setBorderPainted(true);

                               pm.setBackground(new Color(125, 0, 125));

                               pm.add(del);  pm.add(edit);

                               pm.show(lab, e.getX(), e.getY());

                          }

                     }

                     

             });

        }

        

        //内部类,用来访问Frame中的数据成员

        class InputDialog extends Dialog{

            private JLabel ipLabel = new JLabel("IP地址:");

            private JLabel nameLabel = new JLabel("姓名:");

            private JButton okBtn = new JButton("确定");

            private JButton cleBtn = new JButton("取消");

            private JTextField ipText = new JTextField(20);

            private JTextField nameText = new JTextField(20);

            private static final int OKBTN = 1;

            private static final int CANCELBTN = 2;

            private int key = 0;

            private String IP = null, NAME = null; 

            private boolean flag = false;

            void initDialog(){

                JPanel p = null;

                setModal(true);

                setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

                

                add(p = new JPanel());

                p.setLayout(new FlowLayout(FlowLayout.CENTER));

                ipLabel.setPreferredSize(new Dimension(50, 12));

                p.add(ipLabel); p.add(ipText);

                

                

                add(p = new JPanel());

                p.setLayout(new FlowLayout(FlowLayout.CENTER));

                nameLabel.setPreferredSize(new Dimension(50, 12));

                p.add(nameLabel); p.add(nameText);

                

                add(p = new JPanel());

                p.setLayout(new FlowLayout(FlowLayout.CENTER));

                p.add(okBtn); p.add(cleBtn);

                

                addWindowListener(new WindowAdapter() {

                        public void windowClosing(WindowEvent e) {

                             key = 0;

                             dispose();

                        }

                });

                

                addMouseListener(new MouseAdapter() {

                        public void mouseClicked(MouseEvent e) {

                             requestFocus();

                        }

                });

                

                okBtn.addMouseListener(new MouseAdapter() {

                        public void mouseClicked(MouseEvent e) {

                             key = InputDialog.OKBTN;

                             if("".equals(ipText.getText()) || "".equals(nameText.getText()) || !checkIP(ipText.getText()) )

                                     JOptionPane.showMessageDialog(null, "信息不全或者IP填写错误!");

                             else{

                                 String ip = ipText.getText();

                                 if(!flag && QQset.contains(ip)){

                                     JOptionPane.showMessageDialog(null, "好友已存在!", "QQ好友", JOptionPane.OK_OPTION);

                                     return ;

                                 }

                                 IP = ipText.getText();

                                 NAME = nameText.getText();

                                 dispose();

                             }

                        }

                });

                

                cleBtn.addMouseListener(new MouseAdapter() {

                        public void mouseClicked(MouseEvent e) {

                            key = InputDialog.CANCELBTN;

                            dispose();

                        }

                });

                setSize(300, 200);

                setLocation(200, 200);

                setVisible(true);

            }

            

            public InputDialog(String ip, String name){

                super(new Frame());

                ipText.setText(ip);

                nameText.setText(name);

                initDialog();

            }

            

            public InputDialog(String ip, String name, boolean flag){

                super(new Frame());

                ipText.setText(ip);

                nameText.setText(name);

                this.flag = flag;

                initDialog();

            }

            

            public InputDialog(){

                super(new Frame());

                initDialog();

            }

            

            public boolean checkIP(String ip){

                int i, begin = 0, end;

                for(i = 1; i <= 4; ++i){

                    end = ip.indexOf('.', begin);

                    if(end == -1) return false;

                    int p = Integer.valueOf(ip.substring(begin, end));

                    if(p < 0 || p > 255)  return false;

                }

                return true;

            }

            

            public String getIPText(){

                return IP;

            }

            

            public String getNameText(){

                return NAME;

            }

            

        }

        

        

        private static ServerSocketQQ ss = null;

        private static QQReceive qr = null;

        

        public static void main(String[] args){



             ss = new ServerSocketQQ();

             new Thread(ss).start();

             if(ServerSocketQQ.getPort() < 1) return;

             

             qr = new QQReceive();

             new Thread(qr).start();

             if(QQReceive.getPort() < 1)  return ;

             

            new QQDialog();

        }

}
View Code
package testFour;



import java.awt.Color;

import java.awt.Dimension;

import java.awt.FlowLayout;

import java.awt.Font;

import java.awt.Frame;

import java.awt.Label;

import java.awt.TextArea;

import java.awt.event.KeyAdapter;

import java.awt.event.KeyEvent;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

import java.net.InetSocketAddress;

import java.net.Socket;

import java.net.SocketAddress;

import java.net.UnknownHostException;

import java.util.Calendar;

import java.util.Iterator;

import java.util.Map;



import javax.imageio.ImageIO;

import javax.imageio.ImageReader;

import javax.imageio.stream.ImageInputStream;

import javax.swing.BoxLayout;

import javax.swing.JButton;

import javax.swing.JFileChooser;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JTextPane;

import javax.swing.filechooser.FileFilter;







public class QQFrame extends Frame{

     private TextArea taSend = new TextArea();

     private JTextPane taReceive = new JTextPane();

     private JScrollPane p = new JScrollPane(taReceive);

     private JPanel pSend = new JPanel();

     private JPanel pReceive = new JPanel();

     private Label laSend = new Label("发送端.....");

     private Label laReceive = new Label("接收端.....");

     private JButton FileBtn = new JButton("传输文件");

     private JButton PicuterBtn = new JButton("发送图片");

     private InetAddress sendIAD = null;//当前窗口所对应的好友所在机器的IP对象

     private String QQname = null;//该对话框所对应的好友的姓名

     private Socket st =null;

     private String text;

     private DatagramSocket ds = null;

    

     public QQFrame(String name, byte[] ipBuf) throws RuntimeException{

         try {

            sendIAD = InetAddress.getByAddress(ipBuf);

         } catch (UnknownHostException e3) {

            throw new RuntimeException("IP错误(不存在或无发链接)!");

         }

         

         ds = QQReceive.getUdpSocket();

         if(ds == null)  throw new RuntimeException("udp Socket出错!");

         

         QQname = name;

         text = "";

         setSize(600, 600);

         setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

         pSend.setLayout(new FlowLayout(FlowLayout.LEFT));

         pSend.add(laSend);

         pSend.add(FileBtn);

         pSend.add(PicuterBtn);

         pReceive.setLayout(new FlowLayout(FlowLayout.LEFT));

         pReceive.add(laReceive);

         

         taReceive.setForeground(new Color(255, 0, 255));

         add(pReceive);

         add(p);

         add(pSend);

         add(taSend);

         setTitle("我的好友 " + QQname);

         

         

         taSend.setPreferredSize(new Dimension(0, 200));

         taReceive.setPreferredSize(new Dimension(0, 400));

         

         taSend.setFont(new Font("仿宋", Font.PLAIN, 20));

         taReceive.setFont(new Font("黑体", Font.PLAIN, 25));

         

         taReceive.setEditable(false);//不能进行文本的编辑,但是可以进行访问

         

         taSend.addKeyListener(new KeyAdapter() {

            

             public void keyPressed(KeyEvent e) {

                if(e.getKeyCode() == KeyEvent.VK_ENTER){

                     text = taSend.getText();

                     if(text == null) return;

                     text += "\n\n";

                     byte[] bt = text.getBytes();

                     DatagramPacket dp = null;

                     try {

                         //向指定的ip和端口发送数据~!

                         //先说明一下数据是谁发送过来的!

                         byte[] ip = InetAddress.getLocalHost().getHostAddress().getBytes();

                         dp = new DatagramPacket(ip, ip.length, sendIAD, QQReceive.getPort());

                         ds.send(dp);

                         

                         //这里主要是因为多可数据报包发送时会产生丢包的情况...所以暂停一段时间!

                         try {

                            Thread.sleep(100);

                         } catch (InterruptedException e1) {

                         }

                         

                         dp = new DatagramPacket("PARAGRAPH".getBytes(), "PARAGRAPH".getBytes().length, sendIAD, QQReceive.getPort());

                         ds.send(dp);

                         

                         try {

                                Thread.sleep(100);

                         } catch (InterruptedException e1) {

                             

                         }

                         

                         dp = new DatagramPacket(bt, bt.length, sendIAD, QQReceive.getPort());

                         ds.send(dp);

                     } catch (IOException e1) {

                        e1.printStackTrace();

                     }

                     

                     synchronized(QQ.class){//发送端向接收窗口添加数据时 要 和 接收端向接收窗口添加数据时同步!

                         byte[] x = null;

                         try {

                            x = new String(InetAddress.getLocalHost().getHostName() + " : ").getBytes();

                         } catch (UnknownHostException e1) {

                            e1.printStackTrace();

                         }

                         QQ.setTextPane(taReceive, x, x.length, QQ.PARAGRAPH, QQ.SEND);

                         x = text.getBytes();

                         QQ.setTextPane(taReceive, x, x.length, QQ.PARAGRAPH, QQ.SEND*3);

                         taSend.requestFocus();

                     }

                     

                     taSend.setText("");//发送端清空

                     e.consume();//不让这个回车字符在输入端显示!

                     return ;

                }

            }

             

         });

         

         addWindowListener(new WindowAdapter() {



            public void windowClosing(WindowEvent e) {

                Map<String, QQFrame>mp = QQDialog.getMap();

                mp.remove(sendIAD.getHostAddress());

                dispose();

            }

             

         });

         

         FileBtn.addMouseListener(new MouseAdapter() {//文件传输

                public void mouseClicked(MouseEvent e) {

                     JFileChooser jfc = new JFileChooser();

                     jfc.showOpenDialog(null);

                     File fl = jfc.getSelectedFile();

                     if(fl == null) return ;

                     try {

                        st =  new Socket();//尝试连接对方

                        st.connect(new InetSocketAddress(sendIAD, ServerSocketQQ.getPort()), 1000);

                     } catch (IOException e2) {

                        st = null;

                        JOptionPane.showMessageDialog(null, "请求超时或连接错误!", "ServerSocket", JOptionPane.OK_CANCEL_OPTION);

                     }

                     if(st != null){

                        try {

                            byte[] bt = new byte[1024];

                            InputStream is = st.getInputStream(); 

                            OutputStream os = st.getOutputStream();

                            //先说明一下是谁发送过来的!

                            byte[] ip = InetAddress.getLocalHost().getHostAddress().getBytes();

                            os.write(ip);

                            os.flush();

                            

                            try {

                                Thread.sleep(100);

                            } catch (InterruptedException e1) {

                             

                            }

                            

                            //向对方首先发送文件名, 然后发送文件内容!

                            os.write(fl.getName().getBytes());

                            os.flush();

                            

                            try {

                                Thread.sleep(100);

                            } catch (InterruptedException e1) {

                             

                            }

                            

                            int len;

                            InputStream fis = new FileInputStream(fl);

                            while( (len = fis.read(bt)) != -1){

                                os.write(bt, 0, len);

                                os.flush();

                            }

                            bt = new String(Calendar.getInstance().getTime().toString() + ":文件已传输!").getBytes();

                            QQ.setTextPane(taReceive, bt, bt.length, QQ.FILE, QQ.FILEX);

                            st.shutdownOutput();//输出流结束,并标记一下,使服务端知道客户端输出已经结束了!

                            st.close();

                        

                        } catch (IOException e1) {

                            e1.printStackTrace();

                        }

                     }

                }

         });

         

         PicuterBtn.addMouseListener(new MouseAdapter() {

                public void mouseClicked(MouseEvent e) {

                    JFileChooser jfc = new JFileChooser();

                    jfc.setFileFilter(new PicuterFilter());//设置当前的文件过滤器!

                    jfc.setAcceptAllFileFilterUsed(false);//设置所有文件过滤器不使用!

                    //jfc.addChoosableFileFilter(new Filter());

                    jfc.showOpenDialog(null);

                    

                   //将输入流按照下面方式处理, 根据Iterator<ImageReader> itImage是否能

                   //成功的返回一个ImageReader对象确认该流文件是否是一个图片文件!

                   //并ImageReader类中的getFormatName()得到文件的格式!

                   //通过最后可以通过ImageIcon的byte[]构造函数建立ImageIcon对象!

                   //最后将图片显示在面板上!

                    File fl = jfc.getSelectedFile();

                    if(fl == null) return ;

                    try{

                             InputStream is = new FileInputStream(fl);

                             ImageInputStream iis = ImageIO.createImageInputStream(is);

                             Iterator<ImageReader> itImage = ImageIO.getImageReaders(iis);

                             if(itImage.hasNext()){

                                  ImageReader reader = itImage.next();

                                  byte[] imageByte = new byte[1024*64];

                                  int len = iis.read(imageByte);

                                  if(len > 64 * 1000){

                                      JOptionPane.showMessageDialog(new Frame(), "图片过大!请采用文件传输!");

                                      return ;

                                  }

                                  DatagramPacket dp = null;

                                  //先说明一下数据是谁发送过来的!

                                  byte[] ip = InetAddress.getLocalHost().getHostAddress().getBytes();

                                  dp = new DatagramPacket(ip, ip.length, sendIAD, QQReceive.getPort());

                                  ds.send(dp);

                                  

                                  try {

                                        Thread.sleep(100);

                                  } catch (InterruptedException e1) {

                                  }

                                  

                                  dp = new DatagramPacket("PICUTER".getBytes(), "PICUTER".getBytes().length, sendIAD, QQReceive.getPort());

                                  ds.send(dp);

                                  

                                  try {

                                        Thread.sleep(100);

                                  } catch (InterruptedException e1) {

                                  }

                                  

                                  dp = new DatagramPacket(imageByte, len, sendIAD, QQReceive.getPort());

                                  ds.send(dp);

                                  synchronized(QQ.class){

                                      byte[] name = null;

                                      name = new String(InetAddress.getLocalHost().getHostName() + " : ").getBytes();

                                      QQ.setTextPane(taReceive, name, name.length, QQ.PARAGRAPH, QQ.SEND);

                                      QQ.setTextPane(taReceive, imageByte, len, QQ.PICUTER, 0);

                                  }

                             }

                             else throw new NoPicuterException("不是一张图片!");

                    }catch(IOException ex){

                        ex.printStackTrace();

                    }

                }

         });

         

         setVisible(true);

     }

     

     public void setSendIAD(String ip) throws RuntimeException{

         String[] ipStr = ip.split("\\.");//将字符串中的数字分离

         byte[] ipBuf = new byte[4];//存储IP的byte数组

         for(int i = 0; i < 4; i++){

             ipBuf[i] = (byte)(Integer.parseInt(ipStr[i])&0xff);

         }

         try {

             sendIAD = InetAddress.getByAddress(ipBuf);

          } catch (UnknownHostException e3) {

             throw new RuntimeException("IP错误(不存在或无发链接)!");

          }

     }

     

     public DatagramSocket getDs(){

         return ds;

     }

     

     public JTextPane getReceive(){

         return taReceive;

     }

     

}



class PicuterFilter extends FileFilter {

     

    public boolean accept(File file){

           return(file.isDirectory() || file.getName().endsWith(".gif") 

                  || file.getName().endsWith(".png") || file.getName().endsWith(".bmp")

                  || file.getName().endsWith(".jpg") );

           /* 返回要显示的文件类型 */

           /*

            *   File.isDirectory()测试此抽象路径名表示的文件是否是一个目录

           */

      }

      

      public String getDescription() {

          return("Picuter Files(*.gif, *.png, *.jpg, *.bmp)");                  //返回显示文件类型的描述

      }

}



class NoPicuterException extends IOException{

    public NoPicuterException(String x){

        super(x);

    }

}
View Code
package testFour;



import java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.SocketException;

import java.util.Map;

import java.util.Set;



import javax.swing.JOptionPane;



public class QQReceive implements Runnable{

    private QQFrame fm = null;

    private static DatagramSocket ds = null;

    private static int port = 10101;

    private boolean flag = true;

    

    public void setFlag(){

        if(ds != null)

            ds.close();

        flag = false;

    }

    public QQReceive(){

        try {

            //建立udp通信方式

            ds = new DatagramSocket(port);

         } catch (SocketException e1) {

             port = -1;

             JOptionPane.showMessageDialog(null, "DatagramSocket端口绑定错误!", "绑定错误", JOptionPane.OK_CANCEL_OPTION);

        }

    }

    

    public static DatagramSocket getUdpSocket(){

        return ds;

    } 

    

    public static int getPort(){

        return port;

    }

    

    public DatagramSocket getDS(){

        return ds;

    }

    

    public void run(){

        if(ds == null) return ;

        byte[] bt = new byte[10024*10]; 

        DatagramPacket dp = new DatagramPacket(bt, bt.length); 

        while(flag){

            int flagx = 0;

            try {

                    //ds.setReceiveBufferSize(size);

                    ds.receive(dp);

                    String ip = new String(dp.getData(), 0, dp.getLength());

                    

                    ds.receive(dp);

                    String tag = new String(dp.getData(), 0, dp.getLength());

                    

                    ds.receive(dp);

                    

                    Map<String, QQFrame>mp = QQDialog.getMap();

                    Set<String>  set = QQDialog.getSet();

                    fm = mp.get(ip);

                    System.out.println(ip);

                    if(set.contains(ip) && fm == null){//如果存在该好友,但是不存在对应的对话窗口

                         //自动产生对话窗口

                         Map<String, String> nameToIP = QQDialog.getNameToIP();

                         String[] ipStr = ip.split("\\.");//将字符串中的数字分离

                         byte[] ipBuf = new byte[4];//存储IP的byte数组

                         for(int i = 0; i < 4; i++){

                             ipBuf[i] = (byte)(Integer.parseInt(ipStr[i])&0xff);

                         }

                         String name = null;

                         for(String ss : nameToIP.keySet())

                             if( ip.equals(nameToIP.get(ss)) ){

                                   name = ss;

                                   break;

                             }

                         fm = new QQFrame(name, ipBuf);

                    }else if(fm != null){

                         fm.requestFocus();

                    }

                    

                    if( tag.equals("FILE") )

                        flagx = QQ.FILE;

                    else if( tag.equals("PICUTER"))

                        flagx = QQ.PICUTER;

                    else if( tag.equals("PARAGRAPH"))

                        flagx = QQ.PARAGRAPH;

                

            } catch (IOException e) {

                e.printStackTrace();

            }

            synchronized(QQ.class){

                if(fm == null) continue;

                byte[] x = new String(dp.getAddress().getHostName() + " : ").getBytes();

                QQ.setTextPane(fm.getReceive(), x, x.length, QQ.PARAGRAPH, QQ.RECEIVE);

                QQ.setTextPane(fm.getReceive(), dp.getData(), dp.getLength(), flagx, QQ.RECEIVE*3);

            }

        }

    }

}
View Code
package testFour;



import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.Calendar;

import java.util.Map;

import java.util.Set;



import javax.swing.JOptionPane;



public class ServerSocketQQ implements Runnable{

    private ServerSocket sst = null;

    private Socket st = null;

    private static int port = 10100;

    private boolean flag = true;

    

    public void setFlag(){

        if(sst != null)

            try {

                sst.close();

            } catch (IOException e) {

                e.printStackTrace();

            }

        flag = false;

    }

    

    public static int getPort(){

        return port;

    }

    

    public ServerSocketQQ(){

        //建立服务端

        try {

            sst = new ServerSocket(port);

        } catch (IOException e) {

            port = -1;

            JOptionPane.showMessageDialog(null, "ServerSocket端口绑定错误!", "绑定错误", JOptionPane.OK_CANCEL_OPTION);

        }

        

    }

    

    public void run(){

        byte[] bt = null;

        int len = 0;

        if(sst == null)  return ;

        while(true){

            try{

                //侦听并接受到此服务套接字的连接。此方法在进行连接之前一直阻塞。 创建新套接字 

                st = sst.accept();

                //得到客户端传输过来的流

                InputStream is = st.getInputStream();

                OutputStream os  = st.getOutputStream();

                bt = new byte[1024];

                

                len = is.read(bt);

                String name = new String(bt, 0, len);

                QQFrame fm = null;

                Map<String, QQFrame>mp = QQDialog.getMap();

                Set<String>  set = QQDialog.getSet();

                fm = mp.get(name);

                if(set.contains(name) && fm == null){//如果存在该好友,但是不存在对应的对话窗口

                     //自动产生对话窗口

                     Map<String, String> nameToIP = QQDialog.getNameToIP();

                     fm = new QQFrame(name, nameToIP.get(name).getBytes());

                }

                if(fm == null){//对方不存在该好友!

                    st.close();

                    continue;

                }

                

                len = is.read(bt);

                String fileName = new String(bt, 0, len);

                

                int choose = JOptionPane.showConfirmDialog(null, "接受或不接受", "文件传输提示", JOptionPane.YES_NO_OPTION);

                if(choose == JOptionPane.NO_OPTION){

                    bt = new String(Calendar.getInstance().getTime().toString() + ":文件接受失败!").getBytes();

                    QQ.setTextPane(fm.getReceive(), bt, bt.length, QQ.FILE, QQ.FILEX);

                    st.close();

                    continue;

                }

                FileOutputStream fos = new FileOutputStream( new File(fileName) );

                while( (len = is.read(bt)) != -1 ){//先将流文件变成byte[], 然后利用套接字的输出流发送给客户端

                     fos.write(bt);

                     fos.flush();

                }

                bt = new String(Calendar.getInstance().getTime().toString() + ":文件接受成功!").getBytes();

                QQ.setTextPane(fm.getReceive(), bt, bt.length, QQ.FILE, QQ.FILEX);

                st.close();

           }catch(IOException e){

               e.printStackTrace();

           }

        }

     }

    

}
View Code

 

你可能感兴趣的:(java)