posts - 51, comments - 17, trackbacks - 0, articles - 9
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

java UDP

Posted on 2007-04-20 22:50 chenweicai 阅读(897) 评论(0)  编辑  收藏
public class DatagramSocket
extends Object

此类表示用来发送和接收数据报包的套接字

数据报套接字是包投递服务的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。

在 DatagramSocket 上总是启用 UDP 广播发送。为了接收广播包,应该将 DatagramSocket 绑定到通配符地址。在某些实现中,将 DatagramSocket 绑定到一个更加具体的地址时广播包也可以被接收。

示例:DatagramSocket s = new DatagramSocket(null); s.bind(new InetSocketAddress(8888)); 这等价于:DatagramSocket s = new DatagramSocket(8888); 两个例子都能创建能够在 UDP 8888 端口上接收广播的 DatagramSocket。



public final class DatagramPacket
extends Object

此类表示数据报包

数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。



给个具体实现的例子

//UDP数据的发送类似发送寻呼一样的道理。就像寻呼机必须先处于开机接收状态才能接收寻呼一样的道理
//我们先要运行UDP接收程序,再运行UDP发送程序。UDP数据包的接收是过期作废的。
public class UdpSend {

 public static void main(String[] args) throws SocketException, UnknownHostException{
  DatagramSocket ds = new DatagramSocket();//创建用来发送数据报包的套接字
  String str = "Hello World,陈伟才";
  DatagramPacket dp = new DatagramPacket(str.getBytes(), str.getBytes().length,
    InetAddress.getByName("10.214.16.80"), 3000);
  //构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号
  
  try {
   ds.send(dp);
  } catch (IOException e) {
   e.printStackTrace();
  }
  ds.close();
 }
}

public class UdpRecv {

 public static void main(String[] args) throws Exception{
  DatagramSocket ds = new DatagramSocket(3000);//创建接收数据报套接字并将其绑定到本地主机上的指定端口
  byte[] buf = new byte[1024];
  DatagramPacket dp = new DatagramPacket(buf, 1024);
  ds.receive(dp);
  String strRecv = new String (dp.getData(), 0, dp.getLength()) + " from "
  + dp.getAddress().getHostAddress() + ":" + dp.getPort();
  System.out.println(strRecv);
  ds.close();
  
 }
}

再给个例子Chat

public class Chat {

 Frame f = new Frame("我的聊天室");
 
 /*
  * tfIp 是用于输入IP地址的文本框,在发送数据时, 要取出其中的IP地址,
  * 所以将其定义成员变量,以便发送消息的程序代码能访问。
  */
 TextField tfIP = new TextField(15);
 
 /**
  * lst时用于显示接收消息的列表框, 在接收到数据时,要向其中增加新的记录项
  * 所以将其定义成员变量,以便发送消息的程序代码能访问
  */
 List lst = new List(6);
 
 DatagramSocket ds;
 
 public Chat(){
  try{
   ds = new DatagramSocket(3000);
  }catch(Exception e){
   e.printStackTrace();
  }
  
  new Thread (new Runnable(){
   
   public void run(){
    
    byte[] buf = new byte[1024];
    DatagramPacket dp = new DatagramPacket(buf, 1024);
    while (true){
     try{
      ds.receive(dp);
      lst.add(new String(buf, 0 , dp.getLength()) +
        " : form " + dp.getAddress().getHostAddress(), 0);
     }catch(Exception ee){
      ee.printStackTrace();
     }
    }
   }
  }).start();
 }
 
 public void init(){
  f.setSize(300, 300);
  f.add(lst);
  
  Panel p = new Panel();
  p.setLayout(new BorderLayout());
  p.add("West", tfIP);
  TextField tfData = new TextField (20);
  p.add("East", tfData);
  f.add("South", p);
  
  f.setVisible(true);
  f.setResizable(false);//不能改变窗口大小
  
  //增加关闭窗口的事件处理代码
  f.addWindowListener(new WindowAdapter(){
   public void windowClosing(WindowEvent e){
    ds.close();//程序退出时,关闭Socket,释放相关的资源
    f.setVisible(false);
    f.dispose();
    System.exit(0);
   }
  });
  
  //增加在消息文本框中按下回车键的事件处理代码
  tfData.addActionListener(new ActionListener(){
   public void actionPerformed (ActionEvent e){
    //要在这里增加网络消息发送相关程序代码
    //下面的语句用于数据发送后,清空文本框中原来的内容
    
    // 取出文本框的消息字符串,并将其转换成字节数组
    byte[] buf;
    buf = e.getActionCommand().getBytes();
    try {
     DatagramPacket dp = new DatagramPacket(buf, buf.length,
       InetAddress.getByName(tfIP.getText()), 3000);
     try {
      ds.send(dp);
     } catch (IOException e1) {
      e1.printStackTrace();
     }
    } catch (UnknownHostException e1) {
     e1.printStackTrace();
    }
    ((TextField)e.getSource()).setText("");
   }
  });
 }
 
 public static void main(String[] args){
  Chat chat = new Chat();
  chat.init();
 }
}


只有注册用户登录后才能发表评论。


网站导航: