效果图:
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 }
时间: 2024-10-24 10:28:25