黑马程序员技术交流社区

标题: 关于Socket和GUI的一个程序问题!求解啊! [打印本页]

作者: 桃华月禅    时间: 2014-3-14 17:43
标题: 关于Socket和GUI的一个程序问题!求解啊!
正在学习Socket编程,学到了聊天程序,用命令行的方式确实简单实现了,可是自己尝试用GUI做成图形化界面却不知为什么报错?来向即将进黑马学哥学姐求解!

实现效果就是QQ那样的聊天界面。
错误是运行时异常:
第一次点击按钮无论是发送还是接受数据都没问题,可是第二次点击发送按钮就会提示异常。
经过检验是ds.send(dp)那里抛了IOEeption,可是为什么第一次没抛,反而之后的每次都抛呢?真的想不通!

程序代码如下:
  1. import java.io.*;
  2. import java.awt.*;
  3. import java.awt.event.*;
  4. import java.net.*;

  5. class ChattingFrameTest       
  6. {
  7.         public static void main(String[] args)throws Exception{
  8.                 DatagramSocket dsSend = new DatagramSocket();
  9.                 DatagramSocket dsReceive = new DatagramSocket(10000);

  10.                 new ChattingFrame(dsSend,dsReceive);
  11.         }
  12. }

  13. class ChattingFrame
  14. {
  15.         private Frame f;
  16.         private TextArea taSend,taReceive;
  17.         private Panel pSend,pReceive;
  18.         private Button b;
  19.         private DatagramSocket dsSend,dsReceive;

  20.         ChattingFrame(DatagramSocket dsSend,DatagramSocket dsReceive){
  21.                 this.dsSend = dsSend;
  22.                 this.dsReceive = dsReceive;
  23.                 init();
  24.         }

  25.         public void init(){
  26.                 f = new Frame("聊天程序");
  27.                
  28.                 f.setBounds(400,200,500,420);
  29.                 f.setLayout(new BorderLayout(10,10));

  30.                 //建立上下主面板
  31.                 pSend = new Panel();
  32.                 pSend.setPreferredSize(new Dimension(300,100));
  33.                 pReceive = new Panel();
  34.                 pReceive.setPreferredSize(new Dimension(300,300));
  35.                
  36.                 //布局下边的发送面板内的内容
  37.                 pSend.setLayout(new BorderLayout(10,10));
  38.                 taSend = new TextArea();
  39.                 taSend.setPreferredSize(new Dimension(250,60));
  40.                 b = new Button("发送");
  41.                 b.setPreferredSize(new Dimension(30,20));
  42.                 pSend.add(taSend,BorderLayout.CENTER);
  43.                 pSend.add(b,BorderLayout.EAST);

  44.                 //布局上边接收面板的内容
  45.                 pReceive.setLayout(new BorderLayout());
  46.                 taReceive = new TextArea();
  47.                 pReceive.add(taReceive);

  48.                 //把主面板添加进窗体内
  49.                 f.add(pSend,BorderLayout.SOUTH);
  50.                 f.add(pReceive,BorderLayout.CENTER);
  51.                
  52.                 myEvent();
  53.                 f.setVisible(true);
  54.         }

  55.         public void myEvent(){
  56.                 f.addWindowListener(new WindowAdapter(){
  57.                         public void windowClosing(WindowEvent e){
  58.                                 System.exit(0);
  59.                         }
  60.                 });

  61.                 b.addActionListener(new ActionListener(){
  62.                         public void actionPerformed(ActionEvent e){
  63.                                
  64.                                 Receive r = new Receive(dsReceive);
  65.                                
  66.                                 new Thread(new Send(dsSend,taSend.getText())).start();
  67.                                 new Thread(r).start();
  68.                                
  69.                                 try{Thread.sleep(1000);}catch(Exception ei){}

  70.                                 taReceive.append(r.getReceive());
  71.                                 taSend.setText("");
  72.                         }
  73.                 });
  74.         }
  75. }

  76. class Send implements Runnable
  77. {
  78.         private DatagramSocket ds;
  79.         private String taSend;
  80.        
  81.         Send(DatagramSocket ds,String taSend){
  82.                 this.ds = ds;
  83.                 this.taSend = taSend;
  84.         }

  85.         public void run(){
  86.                 try
  87.                 {
  88.                         if(taSend==null)
  89.                                 return;
  90.                         byte[] buf = taSend.getBytes();
  91.                        
  92.                         DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getLocalHost(),10000);

  93.                         ds.send(dp);
  94.                         ds.close();
  95.                 }
  96.                 catch (UnknownHostException e)
  97.                 {
  98.                         throw new RuntimeException("未知主机");
  99.                 }
  100.                 catch(IOException e)
  101.                 {
  102.                         throw new RuntimeException("IO异常");
  103.                 }
  104.         }
  105. }

  106. class Receive implements Runnable
  107. {
  108.         private DatagramSocket ds;
  109.         private String taReceive;
  110.        
  111.         Receive(DatagramSocket ds){
  112.                 this.ds = ds;
  113.         }

  114.         public void run(){
  115.                 try
  116.                 {
  117.                         byte[] buf = new byte[1024];
  118.                        
  119.                         DatagramPacket dp = new DatagramPacket(buf,buf.length);

  120.                         ds.receive(dp);
  121.                        
  122.                         taReceive = dp.getAddress().getHostName()+": \r\n"+new String(dp.getData(),0,dp.getLength())+"\r\n";
  123.                 }
  124.                 catch (Exception e)
  125.                 {
  126.                         throw new RuntimeException("接收出现错误");
  127.                 }
  128.         }

  129.         public String getReceive(){
  130.                 return taReceive;
  131.         }
  132. }
复制代码




作者: daoyua    时间: 2014-3-14 17:51
你把发送那个不要close,因为程序在运行,你关闭了socket第二次怎么发啊,同个线程调用的是一个socket,你试试呢,
作者: 桃华月禅    时间: 2014-3-14 18:00
daoyua 发表于 2014-3-14 17:51
你把发送那个不要close,因为程序在运行,你关闭了socket第二次怎么发啊,同个线程调用的是一个socket,你 ...

不是吧,真的是这么蛋疼的问题,问题确实出现在这里!
自己想了2个多小时都没解决,来这里提问1min就解决了....不是吧,来这里真是来对了= =........
谢谢你的回答,我还需要努力啊。
这个以后确实得注意,都忘了DatagramSocket只建了一个,不能关闭的!
作者: daoyua    时间: 2014-3-14 18:01
因为我和你犯过同样的错,只不过我是输出流~
作者: 桃华月禅    时间: 2014-3-14 18:35
虽说完善程序时还是有点小问题没搞清,不过感觉自己能想出来,总之谢谢了。
继续学习中,不过我不是黑马的学员,虽说可能以后会是,不过我在这里问问题没问题吗?
作者: daoyua    时间: 2014-3-14 18:42
这是技术交流的地方,我也才报名啊,没事的
作者: 桃华月禅    时间: 2014-3-14 18:47
嗯!
这个技术分是什么?我只知道貌似报名时需要,这么容易就给我一年后我不就得好几百分了吗...




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2