首页 > 代码库 > java模拟一个简单的QQ
java模拟一个简单的QQ
效果图:
1 package testFour; 2 3 import java.awt.Color; 4 import java.awt.Dimension; 5 import java.awt.FontMetrics; 6 import java.awt.Graphics; 7 import java.io.ByteArrayInputStream; 8 import java.io.IOException; 9 import java.io.InputStream; 10 import java.net.BindException; 11 import java.net.ServerSocket; 12 import java.util.Iterator; 13 14 import javax.imageio.ImageIO; 15 import javax.imageio.ImageReader; 16 import javax.imageio.stream.ImageInputStream; 17 import javax.swing.ImageIcon; 18 import javax.swing.JLabel; 19 import javax.swing.JPanel; 20 import javax.swing.JTextPane; 21 import javax.swing.text.BadLocationException; 22 import javax.swing.text.Document; 23 import javax.swing.text.SimpleAttributeSet; 24 import javax.swing.text.StyleConstants; 25 26 public class QQ { 27 public static final int PICUTER = 1; 28 public static final int FILE = 2; 29 public static final int PARAGRAPH = 3; 30 public static final int SEND = 1; 31 public static final int RECEIVE = 2; 32 public static final int FILEX = 3; 33 34 public static int getUnusedPort() throws BindException{ 35 int port; 36 for(port = 10000 ; port <= 65535; ++port){ 37 ServerSocket ss = null; 38 try { 39 ss = new ServerSocket(port); 40 } catch (IOException e) { 41 e.printStackTrace(); 42 } 43 if(ss != null) break; 44 } 45 if(port > 65535) 46 throw new BindException("没有可用的端口!"); 47 return port; 48 } 49 50 public synchronized static void setTextPane(JTextPane tp, byte[] bt, int len, int flag, int tag){ 51 ImageIcon myIcon = null; 52 if(tag == SEND) 53 myIcon = new ImageIcon("ff.jpg"); 54 else if(tag == RECEIVE) 55 myIcon = new ImageIcon("gg.jpg"); 56 else if(tag == FILEX) 57 myIcon = new ImageIcon("kk.jpg"); 58 59 SimpleAttributeSet set = new SimpleAttributeSet(); 60 Document doc = tp.getStyledDocument(); 61 62 if(tag == SEND || tag == RECEIVE){ 63 tp.setCaretPosition(doc.getLength()); 64 JLabel fileLabel = new JLabel("", myIcon, JLabel.CENTER); 65 tp.insertComponent(fileLabel); 66 } 67 68 if(flag == PARAGRAPH){ 69 FontMetrics fm = tp.getFontMetrics(tp.getFont()); 70 int paneWidth = tp.getWidth(); 71 String text = new String(bt, 0, len); 72 73 if( tag/3 == SEND ){ 74 StyleConstants.setForeground(set, new Color(0,255,0));//设置文字颜色 75 StyleConstants.setFontSize(set, 15);//设置字体大小 76 } 77 else if( tag/3 == RECEIVE){ 78 StyleConstants.setForeground(set, new Color(0,0,0));//设置文字颜色 79 StyleConstants.setFontSize(set, 15);//设置字体大小 80 } 81 82 try 83 { 84 for(int i = 0, cnt = 0; i < text.length(); ++i){ 85 if((cnt += fm.charWidth(text.charAt(i))) >= paneWidth){ 86 cnt = 0; 87 doc.insertString(doc.getLength(), "\n", set); 88 continue; 89 } 90 doc.insertString(doc.getLength(), String.valueOf(text.charAt(i)), set); 91 } 92 doc.insertString(doc.getLength(), "\n", set); 93 94 tp.setCaretPosition(doc.getLength());//最简单的设置滚动条的位置到最后输出文本的地方 95 //就是将JTextPane中的插入符的位置移动到文本的末端! 96 } 97 catch (BadLocationException e) 98 { 99 }100 101 } else if(flag == PICUTER) {102 103 try{104 InputStream is = new ByteArrayInputStream(bt, 0, len);105 ImageInputStream iis = ImageIO.createImageInputStream(is);106 Iterator<ImageReader> itImage = ImageIO.getImageReaders(iis);107 if(itImage.hasNext()){108 ImageReader reader = itImage.next();109 ImageIcon ii = new ImageIcon( bt, reader.getFormatName() );110 tp.setCaretPosition( doc.getLength() );111 tp.insertComponent( new PicuterPanel(ii) );112 doc.insertString(doc.getLength(), "\n", set);113 }114 }catch(IOException ex){115 ex.printStackTrace();116 }catch(BadLocationException e1){117 118 }119 120 } else if(flag == FILE) {121 try{122 tp.setCaretPosition(doc.getLength());123 JLabel fileLabel = new JLabel(new String(bt, 0, len), myIcon, JLabel.LEFT);124 tp.insertComponent(fileLabel);125 doc.insertString(doc.getLength(), "\n", set);126 }catch (BadLocationException e) {127 e.printStackTrace();128 }129 }130 }131 }132 133 class PicuterPanel extends JPanel{134 private ImageIcon ii;135 public PicuterPanel(ImageIcon ii){136 this.ii = ii;137 setPreferredSize(new Dimension(200, 300));138 setBackground(new Color(255, 255, 255));139 }140 141 protected void paintComponent(Graphics g) {142 super.paintComponent(g);143 g.drawImage(ii.getImage(), 0, 0, 200, 300, 0, 0, ii.getIconWidth(), ii.getIconHeight(), this);144 }145 }
1 package testFour; 2 3 import java.awt.BorderLayout; 4 import java.awt.Color; 5 import java.awt.Dialog; 6 import java.awt.Dimension; 7 import java.awt.FlowLayout; 8 import java.awt.Font; 9 import java.awt.Frame; 10 import java.awt.Point; 11 import java.awt.event.ActionEvent; 12 import java.awt.event.ActionListener; 13 import java.awt.event.MouseAdapter; 14 import java.awt.event.MouseEvent; 15 import java.awt.event.WindowAdapter; 16 import java.awt.event.WindowEvent; 17 import java.net.InetAddress; 18 import java.net.UnknownHostException; 19 import java.util.Map; 20 import java.util.Random; 21 import java.util.Set; 22 import java.util.TreeMap; 23 import java.util.TreeSet; 24 25 import javax.print.attribute.standard.Severity; 26 import javax.swing.BoxLayout; 27 import javax.swing.ImageIcon; 28 import javax.swing.JButton; 29 import javax.swing.JLabel; 30 import javax.swing.JMenuItem; 31 import javax.swing.JOptionPane; 32 import javax.swing.JPanel; 33 import javax.swing.JPopupMenu; 34 import javax.swing.JScrollBar; 35 import javax.swing.JScrollPane; 36 import javax.swing.JTextField; 37 import javax.swing.ScrollPaneConstants; 38 39 40 41 public class QQDialog extends Frame{ 42 private JPanel QQP = new JPanel(); 43 private JButton myFriend = new JButton("QQ好友>>"); 44 private JPanel funP = new JPanel(); 45 private JButton add = new JButton("添加好友"); 46 private JButton serach = new JButton("查询好友"); 47 private JPanel pp = new JPanel(); 48 private JPanel tmp = null; 49 private final int QQPheight = 397; 50 private JScrollPane jsp = new JScrollPane(QQP); 51 private static Set<String>QQset;//姓名的集合 52 private static Map<String, QQFrame>QQmap;//姓名到对通信窗口的映射 53 private static Map<String, byte[]>nameToIP;//姓名到IP的映射 54 ImageIcon[] ii = new ImageIcon[3]; 55 56 public static Map<String, QQFrame> getMap(){ 57 return QQmap; 58 } 59 60 public static Set<String> getSet(){ 61 return QQset; 62 } 63 64 public static Map<String, byte[]> getNameToIP(){ 65 return nameToIP; 66 } 67 68 public QQDialog(){ 69 70 QQset = new TreeSet<String>(); 71 QQmap = new TreeMap<String, QQFrame>(); 72 nameToIP = new TreeMap<String, byte[]>(); 73 74 ii[0] = new ImageIcon("ff.jpg"); 75 ii[1] = new ImageIcon("gg.jpg"); 76 ii[2] = new ImageIcon("kk.jpg"); 77 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 78 jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 79 jsp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 80 pp.add(jsp); 81 pp.setLayout(new BoxLayout(pp, BoxLayout.Y_AXIS)); 82 QQP.setLayout(new BoxLayout(QQP, BoxLayout.Y_AXIS)); 83 JPanel pmyFriend = new JPanel(); 84 pmyFriend.setLayout(new BorderLayout()); 85 pmyFriend.add(myFriend, "Center"); 86 pmyFriend.setPreferredSize(new Dimension(300, 20)); 87 add(pmyFriend); 88 pp.setPreferredSize(new Dimension(300, 400)); 89 add(pp); 90 add(funP); 91 92 JLabel myself = null; 93 try { 94 myself = new JLabel(InetAddress.getLocalHost().getHostName() + ":" + InetAddress.getLocalHost().getHostAddress()); 95 } catch (UnknownHostException e) { 96 e.printStackTrace(); 97 } 98 addLabelListener(myself); 99 myself.setIcon(new ImageIcon("ff.jpg"));100 101 tmp = new JPanel();102 tmp.setLayout(new FlowLayout(FlowLayout.CENTER));103 tmp.setBackground(new Color(255, 0, 255));104 tmp.setPreferredSize(new Dimension(250, 60));105 tmp.add(myself);106 QQP.add(tmp);107 funP.setLayout(new FlowLayout(FlowLayout.CENTER));108 funP.add(add);109 funP.add(serach);110 111 myFriend.addMouseListener(new MouseAdapter() {112 113 public void mouseClicked(MouseEvent e) {//将好友面板进行收缩的效果!114 if("QQ好友>>".equals(myFriend.getText())){115 QQP.setVisible(false);116 myFriend.setText("QQ好友<<");117 }118 else{119 QQP.setVisible(true);120 myFriend.setText("QQ好友>>");121 }122 }123 124 });125 126 add.addMouseListener(new MouseAdapter() {127 public void mouseClicked(MouseEvent e) {128 InputDialog dlg = new InputDialog();129 if(dlg.key == InputDialog.CANCELBTN || dlg.key== 0) return;130 Random rd = new Random();131 int index = Math.abs(rd.nextInt()) % 3;132 JLabel ll = new JLabel(dlg.getNameText() + ":" + dlg.getIPText(), ii[index], JLabel.LEFT);133 tmp = new JPanel();134 tmp.setLayout(new FlowLayout(FlowLayout.CENTER));135 tmp.setBackground(new Color(255, 0, 255));136 137 /*138 * BoxLayout布局简直是蛋疼的要命,一个面板X是BoxLayout布局,如果该面板添加一个面板Y的话139 * 那么Y就会填充X面板!如果在添加一个面板Z, 那么Y, Z就会一起布满X面板!但是可以设置Y,Z面板140 * 的比例! 如果X添加的是一个按钮或者标签时,还不能控制其大小.....无语了!141 * 142 * 下面的我的做法将标签添加到面板tmp中,然后再将tmp添加中QQP面板中!这样就可以控制标签的大小了!143 * 再添加新的面板的时候,要设置一下之前面板的PreferredSize!保证每一个标签的距离适中!144 * 也就是保证所有的添加的面板的高度之和 == QQP.getHeight();145 * */146 int cnt = QQP.getComponentCount();//显示QQ好友的个数!147 if(cnt >= 1)148 QQP.getComponent(cnt-1).setPreferredSize(new Dimension(250, 60));149 int h = QQP.getHeight() - cnt*60;150 if(h < 0) h=60;151 tmp.setPreferredSize(new Dimension(250, h));152 tmp.add(ll);153 QQP.add(tmp);154 QQP.add(tmp);155 addLabelListener(ll);//给标签添加监听器156 JScrollBar jsb = jsp.getVerticalScrollBar();157 QQP.updateUI();//利用当前外观的值重置 UI 属性。 也可以保证滚动条随时的更新158 //终于搞好了,将垂直滚动条自动的移动到最低端159 jsp.getViewport().setViewPosition(new Point(0, jsp.getVerticalScrollBar().getMaximum()));160 }161 });162 163 serach.addMouseListener(new MouseAdapter() {164 public void mouseClicked(MouseEvent e) {165 String name = JOptionPane.showInputDialog(null, "好友姓名", "好友查询", JOptionPane.OK_OPTION);166 if(name == null) return ;167 if(!QQset.contains(name))168 JOptionPane.showMessageDialog(null, "好友不存在!", "查询结果", JOptionPane.OK_OPTION);169 else{170 QQFrame fm = QQmap.get(name);171 if(fm == null){172 try{173 fm = new QQFrame(name, nameToIP.get(name));174 }catch(RuntimeException ex){175 JOptionPane.showMessageDialog(null, ex.getMessage(), "Socket错误!", JOptionPane.OK_CANCEL_OPTION);176 return ;177 }178 QQmap.put(name, fm);179 }180 else fm.requestFocus();181 }182 }183 });184 185 addWindowListener(new WindowAdapter() {186 public void windowClosing(WindowEvent e) {187 if(qr == null) System.out.println("hehe");188 qr.setFlag();//udp服务线程停止189 ss.setFlag();//tcp服务线程停止190 System.exit(0);191 }192 });193 194 QQP.setBackground(new Color(255, 0, 255));195 funP.setBackground(new Color(255, 255, 0));196 setResizable(false);197 setSize(300, 500);198 setLocation(500, 200);199 setVisible(true);200 }201 202 203 public void addLabelListener(final JLabel lab){204 lab.setOpaque(true);205 lab.setBackground(new Color(255, 255, 255));206 lab.setPreferredSize(new Dimension(250, 55));207 208 String NameAndIP = lab.getText();209 String name = NameAndIP.substring(0, NameAndIP.indexOf(‘:‘));210 String ip = NameAndIP.substring(NameAndIP.indexOf(‘:‘) + 1, NameAndIP.length());211 212 String[] ipStr = ip.split("\\.");//将字符串中的数字分离213 byte[] ipBuf = new byte[4];//存储IP的byte数组214 for(int i = 0; i < 4; i++){215 ipBuf[i] = (byte)(Integer.parseInt(ipStr[i])&0xff);216 }217 nameToIP.put(name, ipBuf);218 QQset.add(name);219 220 lab.addMouseListener(new MouseAdapter() {221 Color oldC = lab.getBackground();222 public void mouseEntered(MouseEvent e) {223 lab.setBackground(new Color(0, 255, 0));224 }225 226 public void mouseExited(MouseEvent e) {227 lab.setBackground(oldC);228 }229 230 public void mouseClicked(MouseEvent e) {231 //打开通信窗口232 if(e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2){233 String NameAndIP = lab.getText();234 String name = NameAndIP.substring(0, NameAndIP.indexOf(‘:‘));235 if(QQmap.get(name) != null){//这个好友的窗口已经存在!236 QQmap.get(name).requestFocus();237 return ;238 }239 QQFrame fm = null;240 try{241 fm = new QQFrame(name, nameToIP.get(name));242 }catch(RuntimeException ex){243 JOptionPane.showMessageDialog(null, ex.getMessage(), "Socket错误!", JOptionPane.OK_CANCEL_OPTION);244 return ;245 }246 247 QQmap.put(name, fm);//name 和 窗口的映射!248 }249 else if(e.getButton() == MouseEvent.BUTTON3){250 JPopupMenu pm = new JPopupMenu("胡峻峥");251 JMenuItem del = new JMenuItem("删除");252 del.setFont(new Font("华文行楷", Font.ITALIC, 20));253 del.setForeground(new Color(255, 0, 0));254 del.addActionListener(new ActionListener() {255 public void actionPerformed(ActionEvent e) {256 int choose = JOptionPane.showConfirmDialog(null, "确定删除!", "删除对话框", JOptionPane.YES_NO_OPTION);257 if(choose == JOptionPane.OK_OPTION){258 QQP.remove(lab.getParent());259 int cnt = QQP.getComponentCount();260 int h = QQP.getHeight() - (cnt-1)*60;261 if(h < 0) h=60;262 if(cnt >= 1)263 QQP.getComponent(cnt-1).setPreferredSize(new Dimension(250, h));264 265 cnt = QQP.getComponentCount();266 if(cnt*60 <= QQPheight)267 QQP.setPreferredSize(new Dimension(QQP.getWidth(), QQPheight));268 else 269 QQP.setPreferredSize(new Dimension(QQP.getWidth(), cnt*60));270 QQP.updateUI();271 272 String NameAndIP = lab.getText();273 String name = NameAndIP.substring(0, NameAndIP.indexOf(‘:‘));274 QQset.remove(name);275 QQFrame fm = QQmap.get(name);276 if(fm != null) fm.dispose();277 QQmap.remove(name);278 }279 }280 });281 282 JMenuItem edit = new JMenuItem("编辑");283 edit.addActionListener(new ActionListener() {284 285 public void actionPerformed(ActionEvent e) {286 //得到之前的数据!287 String content = lab.getText();288 //从新设置到文本框中289 InputDialog id = new InputDialog(content.substring(content.indexOf(‘:‘)+1), content.substring(0, content.indexOf(‘:‘)));290 if(id.key == InputDialog.CANCELBTN || id.key== 0) return;291 lab.setText(id.NAME + ":" + id.IP);292 }293 });294 edit.setFont(new Font("华文行楷", Font.ITALIC, 20));295 edit.setForeground(new Color(255, 0, 255));296 pm.setBorderPainted(true);297 pm.setBackground(new Color(125, 0, 125));298 pm.add(del); pm.add(edit);299 pm.show(lab, e.getX(), e.getY());300 }301 }302 303 });304 }305 306 //内部类,用来访问Frame中的数据成员307 class InputDialog extends Dialog{308 private JLabel ipLabel = new JLabel("IP地址:");309 private JLabel nameLabel = new JLabel("姓名:");310 private JButton okBtn = new JButton("确定");311 private JButton cleBtn = new JButton("取消");312 private JTextField ipText = new JTextField(20);313 private JTextField nameText = new JTextField(20);314 private static final int OKBTN = 1;315 private static final int CANCELBTN = 2;316 private int key = 0;317 private String IP = null, NAME = null; 318 void initDialog(){319 JPanel p = null;320 setModal(true);321 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));322 323 add(p = new JPanel());324 p.setLayout(new FlowLayout(FlowLayout.CENTER));325 ipLabel.setPreferredSize(new Dimension(50, 12));326 p.add(ipLabel); p.add(ipText);327 328 329 add(p = new JPanel());330 p.setLayout(new FlowLayout(FlowLayout.CENTER));331 nameLabel.setPreferredSize(new Dimension(50, 12));332 p.add(nameLabel); p.add(nameText);333 334 add(p = new JPanel());335 p.setLayout(new FlowLayout(FlowLayout.CENTER));336 p.add(okBtn); p.add(cleBtn);337 338 addWindowListener(new WindowAdapter() {339 public void windowClosing(WindowEvent e) {340 key = 0;341 dispose();342 }343 });344 345 addMouseListener(new MouseAdapter() {346 public void mouseClicked(MouseEvent e) {347 requestFocus();348 }349 });350 351 okBtn.addMouseListener(new MouseAdapter() {352 public void mouseClicked(MouseEvent e) {353 key = InputDialog.OKBTN;354 if("".equals(ipText.getText()) || "".equals(nameText.getText()) || !checkIP(ipText.getText()) )355 JOptionPane.showMessageDialog(null, "信息不全或者IP填写错误!");356 else{357 String name = nameText.getText();358 if(QQset.contains(name)){359 JOptionPane.showMessageDialog(null, "好友已存在!", "QQ好友", JOptionPane.OK_OPTION);360 return ;361 }362 QQset.add(name);//将新增加的好友添加到集合中!363 IP = ipText.getText();364 NAME = nameText.getText();365 dispose();366 }367 }368 });369 370 cleBtn.addMouseListener(new MouseAdapter() {371 public void mouseClicked(MouseEvent e) {372 key = InputDialog.CANCELBTN;373 dispose();374 }375 });376 setSize(300, 200);377 setLocation(200, 200);378 setVisible(true);379 }380 381 public InputDialog(String ip, String name){382 super(new Frame());383 ipText.setText(ip);384 nameText.setText(name);385 initDialog();386 }387 388 public InputDialog(){389 super(new Frame());390 initDialog();391 }392 393 public boolean checkIP(String ip){394 int i, begin = 0, end;395 for(i = 1; i <= 4; ++i){396 end = ip.indexOf(‘.‘, begin);397 if(end == -1) return false;398 int p = Integer.valueOf(ip.substring(begin, end));399 if(p < 0 || p > 255) return false;400 }401 return true;402 }403 404 public String getIPText(){405 return IP;406 }407 408 public String getNameText(){409 return NAME;410 }411 412 }413 414 415 private static ServerSocketQQ ss = null;416 private static QQReceive qr = null;417 418 public static void main(String[] args){419 420 ss = new ServerSocketQQ();421 new Thread(ss).start();422 if(ServerSocketQQ.getPort() < 1) return;423 424 qr = new QQReceive();425 new Thread(qr).start();426 if(qr.getPort() < 1) return ;427 428 new QQDialog();429 }430 }
1 package testFour; 2 3 import java.awt.Color; 4 import java.awt.Dimension; 5 import java.awt.FlowLayout; 6 import java.awt.Font; 7 import java.awt.Frame; 8 import java.awt.Label; 9 import java.awt.TextArea; 10 import java.awt.event.KeyAdapter; 11 import java.awt.event.KeyEvent; 12 import java.awt.event.MouseAdapter; 13 import java.awt.event.MouseEvent; 14 import java.awt.event.WindowAdapter; 15 import java.awt.event.WindowEvent; 16 import java.io.File; 17 import java.io.FileInputStream; 18 import java.io.IOException; 19 import java.io.InputStream; 20 import java.io.OutputStream; 21 import java.net.DatagramPacket; 22 import java.net.DatagramSocket; 23 import java.net.InetAddress; 24 import java.net.InetSocketAddress; 25 import java.net.Socket; 26 import java.net.SocketAddress; 27 import java.net.UnknownHostException; 28 import java.util.Calendar; 29 import java.util.Iterator; 30 import java.util.Map; 31 32 import javax.imageio.ImageIO; 33 import javax.imageio.ImageReader; 34 import javax.imageio.stream.ImageInputStream; 35 import javax.swing.BoxLayout; 36 import javax.swing.JButton; 37 import javax.swing.JFileChooser; 38 import javax.swing.JOptionPane; 39 import javax.swing.JPanel; 40 import javax.swing.JScrollPane; 41 import javax.swing.JTextPane; 42 import javax.swing.filechooser.FileFilter; 43 44 45 46 public class QQFrame extends Frame{ 47 private TextArea taSend = new TextArea(); 48 private JTextPane taReceive = new JTextPane(); 49 private JScrollPane p = new JScrollPane(taReceive); 50 private JPanel pSend = new JPanel(); 51 private JPanel pReceive = new JPanel(); 52 private Label laSend = new Label("发送端....."); 53 private Label laReceive = new Label("接收端....."); 54 private JButton FileBtn = new JButton("传输文件"); 55 private JButton PicuterBtn = new JButton("发送图片"); 56 private InetAddress sendIAD = null;//当前窗口所对应的好友所在机器的IP对象 57 private String QQname = null;//该对话框所对应的好友的姓名 58 private Socket st =null; 59 private String text; 60 private DatagramSocket ds = null; 61 62 public QQFrame(String name, byte[] ipBuf) throws RuntimeException{ 63 try { 64 sendIAD = InetAddress.getByAddress(ipBuf); 65 } catch (UnknownHostException e3) { 66 JOptionPane.showMessageDialog(null, "IP错误", "错误类型", JOptionPane.OK_CANCEL_OPTION); 67 return ; 68 } 69 70 ds = QQReceive.getUdpSocket(); 71 if(ds == null) throw new RuntimeException("udp Socket出错!"); 72 73 QQname = name; 74 text = ""; 75 setSize(600, 600); 76 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 77 pSend.setLayout(new FlowLayout(FlowLayout.LEFT)); 78 pSend.add(laSend); 79 pSend.add(FileBtn); 80 pSend.add(PicuterBtn); 81 pReceive.setLayout(new FlowLayout(FlowLayout.LEFT)); 82 pReceive.add(laReceive); 83 84 taReceive.setForeground(new Color(255, 0, 255)); 85 add(pReceive); 86 add(p); 87 add(pSend); 88 add(taSend); 89 setTitle("我的好友 " + QQname); 90 91 92 taSend.setPreferredSize(new Dimension(0, 200)); 93 taReceive.setPreferredSize(new Dimension(0, 400)); 94 95 taSend.setFont(new Font("仿宋", Font.PLAIN, 20)); 96 taReceive.setFont(new Font("黑体", Font.PLAIN, 25)); 97 98 taReceive.setEditable(false);//不能进行文本的编辑,但是可以进行访问 99 100 taSend.addKeyListener(new KeyAdapter() {101 102 public void keyPressed(KeyEvent e) {103 if(e.getKeyCode() == KeyEvent.VK_ENTER){104 text = taSend.getText();105 if(text == null) return;106 text += "\n\n";107 byte[] bt = text.getBytes();108 DatagramPacket dp = null;109 try {110 //向指定的ip和端口发送数据~!111 //先说明一下数据是谁发送过来的!112 dp = new DatagramPacket(QQname.getBytes(), QQname.getBytes().length, sendIAD, QQReceive.getPort());113 ds.send(dp);114 115 dp = new DatagramPacket("PARAGRAPH".getBytes(), "PARAGRAPH".getBytes().length, sendIAD, QQReceive.getPort());116 ds.send(dp);117 dp = new DatagramPacket(bt, bt.length, sendIAD, QQReceive.getPort());118 ds.send(dp);119 } catch (IOException e1) {120 e1.printStackTrace();121 }122 123 synchronized(QQ.class){//发送端向接收窗口添加数据时 要 和 接收端向接收窗口添加数据时同步!124 byte[] x = new String(QQname + " : ").getBytes();125 QQ.setTextPane(taReceive, x, x.length, QQ.PARAGRAPH, QQ.SEND);126 x = text.getBytes();127 QQ.setTextPane(taReceive, x, x.length, QQ.PARAGRAPH, QQ.SEND*3);128 }129 130 taSend.setText("");//发送端清空131 e.consume();//不让这个回车字符在输入端显示!132 return ;133 }134 }135 136 });137 138 addWindowListener(new WindowAdapter() {139 140 public void windowClosing(WindowEvent e) {141 Map<String, QQFrame>mp = QQDialog.getMap();142 mp.remove(QQname);143 dispose();144 }145 146 });147 148 FileBtn.addMouseListener(new MouseAdapter() {//文件传输149 public void mouseClicked(MouseEvent e) {150 JFileChooser jfc = new JFileChooser();151 jfc.showOpenDialog(null);152 File fl = jfc.getSelectedFile();153 if(fl == null) return ;154 try {155 st = new Socket();//尝试连接对方156 st.connect(new InetSocketAddress(sendIAD, ServerSocketQQ.getPort()), 1000);157 } catch (IOException e2) {158 st = null;159 JOptionPane.showMessageDialog(null, "连接错误!", "ServerSocket", JOptionPane.OK_CANCEL_OPTION);160 }161 if(st != null){162 try {163 byte[] bt = new byte[1024];164 InputStream is = st.getInputStream(); 165 OutputStream os = st.getOutputStream();166 //先说明一下是谁发送过来的!167 os.write(QQname.getBytes());168 os.flush();169 170 //向对方首先发送文件名, 然后发送文件内容!171 os.write(fl.getName().getBytes());172 os.flush();173 174 int len;175 InputStream fis = new FileInputStream(fl);176 while( (len = fis.read(bt)) != -1){177 os.write(bt, 0, len);178 os.flush();179 }180 bt = new String(Calendar.getInstance().getTime().toString() + ":文件已传输!").getBytes();181 QQ.setTextPane(taReceive, bt, bt.length, QQ.FILE, QQ.FILEX);182 st.shutdownOutput();//输出流结束,并标记一下,使服务端知道客户端输出已经结束了!183 st.close();184 185 } catch (IOException e1) {186 e1.printStackTrace();187 }188 }189 }190 });191 192 PicuterBtn.addMouseListener(new MouseAdapter() {193 public void mouseClicked(MouseEvent e) {194 JFileChooser jfc = new JFileChooser();195 jfc.setFileFilter(new PicuterFilter());//设置当前的文件过滤器!196 jfc.setAcceptAllFileFilterUsed(false);//设置所有文件过滤器不使用!197 //jfc.addChoosableFileFilter(new Filter());198 jfc.showOpenDialog(null);199 200 //将输入流按照下面方式处理, 根据Iterator<ImageReader> itImage是否能201 //成功的返回一个ImageReader对象确认该流文件是否是一个图片文件!202 //并ImageReader类中的getFormatName()得到文件的格式!203 //通过最后可以通过ImageIcon的byte[]构造函数建立ImageIcon对象!204 //最后将图片显示在面板上!205 File fl = jfc.getSelectedFile();206 if(fl == null) return ;207 try{208 InputStream is = new FileInputStream(fl);209 ImageInputStream iis = ImageIO.createImageInputStream(is);210 Iterator<ImageReader> itImage = ImageIO.getImageReaders(iis);211 if(itImage.hasNext()){212 ImageReader reader = itImage.next();213 byte[] imageByte = new byte[1024*64];214 int len = iis.read(imageByte);215 if(len > 64 * 1000){216 JOptionPane.showMessageDialog(new Frame(), "图片过大!请采用文件传输!");217 return ;218 }219 DatagramPacket dp = null;220 //先说明一下数据是谁发送过来的!221 dp = new DatagramPacket(QQname.getBytes(), QQname.getBytes().length, sendIAD, QQReceive.getPort());222 ds.send(dp);223 224 dp = new DatagramPacket("PICUTER".getBytes(), "PICUTER".getBytes().length, InetAddress.getLocalHost(), QQReceive.getPort());225 ds.send(dp);226 dp = new DatagramPacket(imageByte, len, InetAddress.getLocalHost(), QQReceive.getPort());227 ds.send(dp);228 synchronized(QQ.class){229 byte[] name = new String(dp.getAddress().getHostName() + " : ").getBytes();230 QQ.setTextPane(taReceive, name, name.length, QQ.PARAGRAPH, QQ.SEND);231 QQ.setTextPane(taReceive, imageByte, len, QQ.PICUTER, 0);232 }233 }234 else throw new NoPicuterException("不是一张图片!");235 }catch(IOException ex){236 ex.printStackTrace();237 }238 }239 });240 241 setVisible(true);242 }243 244 public DatagramSocket getDs(){245 return ds;246 }247 248 public JTextPane getReceive(){249 return taReceive;250 }251 252 }253 254 class PicuterFilter extends FileFilter {255 256 public boolean accept(File file){257 return(file.isDirectory() || file.getName().endsWith(".gif") 258 || file.getName().endsWith(".png") || file.getName().endsWith(".bmp")259 || file.getName().endsWith(".jpg") );260 /* 返回要显示的文件类型 */261 /*262 * File.isDirectory()测试此抽象路径名表示的文件是否是一个目录263 */264 }265 266 public String getDescription() {267 return("Picuter Files(*.gif, *.png, *.jpg, *.bmp)"); //返回显示文件类型的描述268 }269 }270 271 class NoPicuterException extends IOException{272 public NoPicuterException(String x){273 super(x);274 }275 }
1 package testFour; 2 3 import java.io.IOException; 4 import java.net.DatagramPacket; 5 import java.net.DatagramSocket; 6 import java.net.SocketException; 7 import java.util.Map; 8 import java.util.Set; 9 10 import javax.swing.JOptionPane;11 12 public class QQReceive implements Runnable{13 private QQFrame fm = null;14 private static DatagramSocket ds = null;15 private static int port = 10101;16 private boolean flag = true;17 18 public void setFlag(){19 if(ds != null)20 ds.close();21 flag = false;22 }23 public QQReceive(){24 try {25 //建立udp通信方式26 ds = new DatagramSocket(port);27 } catch (SocketException e1) {28 port = -1;29 JOptionPane.showMessageDialog(null, "DatagramSocket端口绑定错误!", "绑定错误", JOptionPane.OK_CANCEL_OPTION);30 }31 }32 33 public static DatagramSocket getUdpSocket(){34 return ds;35 } 36 37 public static int getPort(){38 return port;39 }40 41 public DatagramSocket getDS(){42 return ds;43 }44 45 public void run(){46 if(ds == null) return ;47 while(flag){48 byte[] bt = new byte[10024*10]; 49 int flag = 0;50 DatagramPacket dp = new DatagramPacket(bt, bt.length); 51 try {52 ds.receive(dp);53 54 String name = new String(dp.getData(), 0, dp.getLength());55 Map<String, QQFrame>mp = QQDialog.getMap();56 Set<String> set = QQDialog.getSet();57 fm = mp.get(name);58 if(set.contains(name) && fm == null){//如果存在该好友,但是不存在对应的对话窗口59 //自动产生对话窗口60 Map<String, byte[]> nameToIP = QQDialog.getNameToIP();61 fm = new QQFrame(name, nameToIP.get(name));62 }63 ds.receive(dp);64 String tag = new String(dp.getData(), 0, dp.getLength());65 if( tag.equals("FILE") )66 flag = QQ.FILE;67 else if( tag.equals("PICUTER"))68 flag = QQ.PICUTER;69 else if( tag.equals("PARAGRAPH"))70 flag = QQ.PARAGRAPH;71 72 ds.receive(dp);73 74 } catch (IOException e) {75 e.printStackTrace();76 }77 synchronized(QQ.class){78 if(fm == null) continue;79 byte[] x = new String(dp.getAddress().getHostName() + " : ").getBytes();80 QQ.setTextPane(fm.getReceive(), x, x.length, QQ.PARAGRAPH, QQ.RECEIVE);81 QQ.setTextPane(fm.getReceive(), dp.getData(), dp.getLength(), flag, QQ.RECEIVE*3);82 }83 }84 }85 }
1 package testFour; 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.OutputStream; 8 import java.net.ServerSocket; 9 import java.net.Socket; 10 import java.util.Calendar; 11 import java.util.Map; 12 import java.util.Set; 13 14 import javax.swing.JOptionPane; 15 16 public class ServerSocketQQ implements Runnable{ 17 private ServerSocket sst = null; 18 private Socket st = null; 19 private static int port = 10100; 20 private boolean flag = true; 21 22 public void setFlag(){ 23 if(sst != null) 24 try { 25 sst.close(); 26 } catch (IOException e) { 27 e.printStackTrace(); 28 } 29 flag = false; 30 } 31 32 public static int getPort(){ 33 return port; 34 } 35 36 public ServerSocketQQ(){ 37 //建立服务端 38 try { 39 sst = new ServerSocket(port); 40 } catch (IOException e) { 41 port = -1; 42 JOptionPane.showMessageDialog(null, "ServerSocket端口绑定错误!", "绑定错误", JOptionPane.OK_CANCEL_OPTION); 43 } 44 45 } 46 47 public void run(){ 48 byte[] bt = null; 49 int len = 0; 50 if(sst == null) return ; 51 while(true){ 52 try{ 53 //侦听并接受到此服务套接字的连接。此方法在进行连接之前一直阻塞。 创建新套接字 54 st = sst.accept(); 55 //得到客户端传输过来的流 56 InputStream is = st.getInputStream(); 57 OutputStream os = st.getOutputStream(); 58 bt = new byte[1024]; 59 60 len = is.read(bt); 61 String name = new String(bt, 0, len); 62 QQFrame fm = null; 63 Map<String, QQFrame>mp = QQDialog.getMap(); 64 Set<String> set = QQDialog.getSet(); 65 fm = mp.get(name); 66 if(set.contains(name) && fm == null){//如果存在该好友,但是不存在对应的对话窗口 67 //自动产生对话窗口 68 Map<String, byte[]> nameToIP = QQDialog.getNameToIP(); 69 fm = new QQFrame(name, nameToIP.get(name)); 70 } 71 if(fm == null){//对方不存在该好友! 72 st.close(); 73 continue; 74 } 75 76 len = is.read(bt); 77 String fileName = new String(bt, 0, len); 78 79 int choose = JOptionPane.showConfirmDialog(null, "接受或不接受", "文件传输提示", JOptionPane.YES_NO_OPTION); 80 if(choose == JOptionPane.NO_OPTION){ 81 bt = new String(Calendar.getInstance().getTime().toString() + ":文件接受失败!").getBytes(); 82 QQ.setTextPane(fm.getReceive(), bt, bt.length, QQ.FILE, QQ.FILEX); 83 st.close(); 84 continue; 85 } 86 FileOutputStream fos = new FileOutputStream( new File(fileName) ); 87 while( (len = is.read(bt)) != -1 ){//先将流文件变成byte[], 然后利用套接字的输出流发送给客户端 88 fos.write(bt); 89 fos.flush(); 90 } 91 bt = new String(Calendar.getInstance().getTime().toString() + ":文件接受成功!").getBytes(); 92 QQ.setTextPane(fm.getReceive(), bt, bt.length, QQ.FILE, QQ.FILEX); 93 st.close(); 94 }catch(IOException e){ 95 e.printStackTrace(); 96 } 97 } 98 } 99 100 }
java模拟一个简单的QQ
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。