Java中的UDP协议编程

导读:
  阿蜜果
  不骄,不矜,勤工,好学,才是好女子
  UDP协议的全称是用户数据报,在网络中它与TCP协议一样用于处理数据包。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据报分组、组装和不能对数据包的排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。
   二. 使用UDP的原因
  它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的ICQ和OICQ就是使用的UDP协议。在选择使用协议的时候,选择UDP必须要谨慎。在网络质量令人不十分满意的环境下,UDP协议数据包丢失会比较严重。
   三. 在Java中使用UDP协议编程的相关类
  1. InetAddress
  用于描述和包装一个Internet IP地址。有如下方法返回实例:
  getLocalhost():返回封装本地地址的实例。
  getAllByName(String host):返回封装Host地址的InetAddress实例数组。
  getByName(String host):返回一个封装Host地址的实例。其中,Host可以是域名或者是一个合法的IP地址。
  InetAddress.getByAddress(addr):根据地址串返回InetAddress实例。
  InetAddress.getByAddress(host, addr):根据主机地符串和地址串返回InetAddress实例。
  2. DatagramSocket
  用于接收和发送UDP的Socket实例。该类有3个构造函数:
  DatagramSocket():通常用于客户端编程,它并没有特定监听的端口,仅仅使用一个临时的。程序会让操作系统分配一个可用的端口。
  DatagramSocket(int port):创建实例,并固定监听Port端口的报文。通常用于服务端
  DatagramSocket(int port, InetAddress localAddr):这是个非常有用的构建器,当一台机器拥有多于一个IP地址的时候,由它创建的实例仅仅接收来自LocalAddr的报文。
  DatagramSocket具有的主要方法如下:
  1)receive(DatagramPacket d):接收数据报文到d中。receive方法产生一个“阻塞”。“阻塞”是一个专业名词,它会产生一个内部循环,使程序暂停在这个地方,直到一个条件触发。
  2)send(DatagramPacket dp):发送报文dp到目的地。
  3)setSoTimeout(int timeout):设置超时时间,单位为毫秒。
  4)close():关闭DatagramSocket。在应用程序退出的时候,通常会主动释放资源,关闭Socket,但是由于异常地退出可能造成资源无法回收。所以,应该在程序完成时,主动使用此方法关闭Socket,或在捕获到异常抛出后关闭Socket。
  3. DatagramPacket
  用于处理报文,它将Byte数组、目标地址、目标端口等数据包装成报文或者将报文拆卸成Byte数组。应用程序在产生数据包是应该注意,TCP/IP规定数据报文大小最多包含65507个,通常主机接收548个字节,但大多数平台能够支持8192字节大小的报文。DatagramPacket类的构建器共有4个:
  DatagramPacket(byte[] buf, int length):将数据包中Length长的数据装进Buf数组,一般用来接收客户端发送的数据。
  DatagramPacket(byte[] buf, int offset, int length):将数据包中从Offset开始、Length长的数据装进Buf数组。
  DatagramPacket(byte[] buf, int length, InetAddress clientAddress, int clientPort):从Buf数组中,取出Length长的数据创建数据包对象,目标是clientAddress地址,clientPort端口,通常用来发送数据给客户端。
  DatagramPacket(byte[] buf, int offset, int length, InetAddress clientAddress, int clientPort):从Buf数组中,取出Offset开始的、Length长的数据创建数据包对象,目标是clientAddress地址,clientPort端口,通常用来发送数据给客户端。
  主要的方法如下:
  1)getData(): 从实例中取得报文的Byte数组编码。
  2)setDate(byte[] buf):将byte数组放入要发送的报文中。
   四. 实例解析
  下面让我们来看一个UDP的服务端和客户端交互通信的例子,在本例中,服务端循环等待客户端发送的信息,并对其进行回应,客户端向服务端发送信息,并接收服务端的回应信息。代码如下:
  1. UDP的服务端程序
  import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.InetSocketAddress;import java.net.SocketException;/** * Copyright 2007 GuangZhou Cotel Co. Ltd.
  * All right reserved.
  * UTP服务类.
  * @author AmigoXie
  * @version 1.0
  * Creation date: 2007-8-16 - 下午10:32:31
  */public class UdpServerSocket {
  private byte[] buffer = new byte[1024];
  
  private DatagramSocket ds = null private DatagramPacket packet = null private InetSocketAddress socketAddress = null private String orgIp;
  /** * 构造函数,绑定主机和端口.
  * @param host 主机
  * @param port 端口
  * @throws Exception
  */ public UdpServerSocket(String host, int port) throws Exception {
  socketAddress = new InetSocketAddress(host, port);
  ds = new DatagramSocket(socketAddress);
  System.out.println("服务端启动!");
  }
  public final String getOrgIp() {
  return orgIp;
  } /** * 设置超时时间,该方法必须在bind方法之后使用.
  * @param timeout 超时时间
  * @throws Exception
  */ public final void setSoTimeout(int timeout) throws Exception {
  ds.setSoTimeout(timeout);
  } /** * 获得超时时间.
  * @return 返回超时时间.
  * @throws Exception
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午10:34:36
  */ public final int getSoTimeout() throws Exception {
  return ds.getSoTimeout();
  } /** * 绑定监听地址和端口.
  * @param host 主机IP
  * @param port 端口
  * @throws SocketException
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午10:36:17
  */ public final void bind(String host, int port) throws SocketException {
  socketAddress = new InetSocketAddress(host, port);
  ds = new DatagramSocket(socketAddress);
  } /** * 接收数据包,该方法会造成线程阻塞.
  * @return 返回接收的数据串信息
  * @throws IOException
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午10:38:24
  */ public final String receive() throws IOException {
  packet = new DatagramPacket(buffer, buffer.length);
  ds.receive(packet);
  orgIp = packet.getAddress().getHostAddress();
  String info = new String(packet.getData(), 0, packet.getLength());
  System.out.println("接收信息:" + info);
  return info;
  } /** * 将响应包发送给请求端.
  * @param bytes 回应报文
  * @throws IOException
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午11:05:31
  */ public final void response(String info) throws IOException {
  System.out.println("客户端地址 : " + packet.getAddress().getHostAddress()
  + ",端口:" + packet.getPort());
  DatagramPacket dp = new DatagramPacket(buffer, buffer.length, packet
  .getAddress(), packet.getPort());
  dp.setData(info.getBytes());
  ds.send(dp);
  } /** * 设置报文的缓冲长度.
  * @param bufsize 缓冲长度
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午10:47:49
  */ public final void setLength(int bufsize) {
  packet.setLength(bufsize);
  } /** * 获得发送回应的IP地址.
  * @return 返回回应的IP地址
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午10:48:27
  */ public final InetAddress getResponseAddress() {
  return packet.getAddress();
  } /** * 获得回应的主机的端口.
  * @return 返回回应的主机的端口.
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午10:48:56
  */ public final int getResponsePort() {
  return packet.getPort();
  } /** * 关闭udp监听口.
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午10:49:23
  */ public final void close() {
  try {
  ds.close();
  } catch (Exception ex) {
  ex.printStackTrace();
  } } /** * 测试方法.
  * @param args
  * @throws Exception
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午10:49:50
  */ public static void main(String[] args) throws Exception {
  String serverHost = "127.0.0.1" int serverPort = 3344 UdpServerSocket udpServerSocket = new UdpServerSocket(serverHost, serverPort);
  while (true) {
  udpServerSocket.receive();
  udpServerSocket.response("你好,sterning!");
  
  } }}
  2. UDP客户端程序
  import java.io.*import java.net.*/** * Copyright 2007 GuangZhou Cotel Co. Ltd.
  * All right reserved.
  * UDP客户端程序,用于对服务端发送数据,并接收服务端的回应信息.
  * @author AmigoXie
  * @version 1.0
  * Creation date: 2007-8-16 - 下午10:54:23
  */public class UdpClientSocket {
  private byte[] buffer = new byte[1024];
  private DatagramSocket ds = null /** * 构造函数,创建UDP客户端
  * @throws Exception
  */ public UdpClientSocket() throws Exception {
  ds = new DatagramSocket();
  }
  /** * 设置超时时间,该方法必须在bind方法之后使用.
  * @param timeout 超时时间
  * @throws Exception
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午10:55:12
  */ public final void setSoTimeout(final int timeout) throws Exception {
  ds.setSoTimeout(timeout);
  } /** * 获得超时时间.
  * @return 返回超时时间
  * @throws Exception
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午10:55:25
  */ public final int getSoTimeout() throws Exception {
  return ds.getSoTimeout();
  } public final DatagramSocket getSocket() {
  return ds;
  } /** * 向指定的服务端发送数据信息.
  * @param host 服务器主机地址
  * @param port 服务端端口
  * @param bytes 发送的数据信息
  * @return 返回构造后俄数据报
  * @throws IOException
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午11:02:41
  */ public final DatagramPacket send(final String host, final int port,
  final byte[] bytes) throws IOException {
  DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress
  .getByName(host), port);
  ds.send(dp);
  return dp;
  } /** * 接收从指定的服务端发回的数据.
  * @param lhost 服务端主机
  * @param lport 服务端端口
  * @return 返回从指定的服务端发回的数据.
  * @throws Exception
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午10:52:36
  */ public final String receive(final String lhost, final int lport)
  throws Exception {
  DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
  ds.receive(dp);
  String info = new String(dp.getData(), 0, dp.getLength());
  return info;
  } /** * 关闭udp连接.
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午10:53:52
  */ public final void close() {
  try {
  ds.close();
  } catch (Exception ex) {
  ex.printStackTrace();
  } } /** * 测试客户端发包和接收回应信息的方法.
  * @param args
  * @throws Exception
  * @author AmigoXie
  * Creation date: 2007-8-16 - 下午11:03:54
  */ public static void main(String[] args) throws Exception {
  UdpClientSocket client = new UdpClientSocket();
  String serverHost = "127.0.0.1" int serverPort = 3344 client.send(serverHost, serverPort, ("你好,阿蜜果!").getBytes());
  String info = client.receive(serverHost, serverPort);
  System.out.println("服务端回应数据:" + info);
  }}
  参考文章:http://java.photoshopjiaocheng.com/sun-applet-class/sdk-api-code/virtual-machine-programming-9178.html
  http://www.eoot.cn/html/pro/java/20070511/25276.html
  http://topic.csdn.net/t/20060204/19/4539686.html
  阿蜜果评论(8)编辑收藏网络通信相关
   FeedBack:
  # re: Java中的UDP协议编程[未登录]
  -274C
  沙发哦。呵呵。
  写得好。 回复 更多评论
  
  # re: Java中的UDP协议编程
  杨爱友
  运行过了,以前学过网络,还比较容易看懂 回复 更多评论
  
  # re: Java中的UDP协议编程
  Scott.Pan
  新文章哦,不错!
  暂时还没接触协议编程,希望有机会向你学习! 回复 更多评论
  
  # re: Java中的UDP协议编程
  三告习习
  学习,先记下了
  现在都直接用了ice,都还不懂udp...回头再看看
  :)
  回复 更多评论
  
  # re: Java中的UDP协议编程
  BeanSoft
  保存, 支持. 不理解原理用类库, 出了问题怎么改? 所以还是要掌握基础的. 回复 更多评论
  
  # re: Java中的UDP协议编程[未登录]
  Jack
  非常好,懂了 回复 更多评论
  
  # re: Java中的UDP协议编程
  norvid
  有疑问!
  客户端中为什么方法
  public final String receive(final String lhost, final int lport) throws Exception;
  的两个参数lhost, lport在方法体内没有用到?如果说这两个参数不起作用,那为什么还要作为参数呢? 回复 更多评论
  
  # re: Java中的UDP协议编程
  好东西啊~~
  终于找到比较全的UDP编程文章了 回复 更多评论
  
  标题
  姓名
  主页
  验证码 *
  
  
  内容(请不要发表任何与政治相关的内容)
  
  Remember Me?
  [使用Ctrl+Enter键可以直接提交]
  该文被作者在 2007-08-22 18:21 编辑过
  
  
  Copyright 2008 阿蜜果 Powered by: 博客园模板提供:沪江博客
   2007年8月
  
  29 30 31 3 4
  5 6 11
  19 21 25
  26 29 1
  2 3 4 5 6 7 8
  
  
  錢為人用無需多,人為錢忙凈白忙
   留言簿(114)
  给我留言
  
  
   随笔分类
  Ajax(2)
  Ant(1)
  Auto Code(4)
  Cewolf
  CMMI(1)
  CSS(2)
  CVS(1)
  Design Pattern(7)
  Eclipse BIRT
  EJB
  extremecomponents(1)
  GIS(2)
  Hibernate(8)
  iBATIS(2)
  Inno Setup(2)
  Java(19)
  Javascript(25)
  JBoss(1)
  JFreeChart(2)
  JFreeReport(2)
  JSF
  MySql(10)
  Open Source(4)
  Oracle(4)
  Other(9)
  Spring(12)
  Sql Server(1)
  Struts(7)
  Struts2(8)
  Tomcat
  UML
  Web(1)
  Web Service(2)
  Workflow
  似水流年(35)
  网络通信相关(6)
  项目管理(3)
   随笔档案
  2008年2月 (2)
  2008年1月 (12)
  2007年12月 (10)
  2007年11月 (13)
  2007年10月 (11)
  2007年9月 (13)
  2007年8月 (26)
  2007年7月 (12)
  2007年6月 (3)
  2007年5月 (4)
  2007年4月 (23)
  2007年3月 (32)
  2007年2月 (26)
   文章分类
  喜爱歌词(12)
  生活点滴(3)
  芝麻粒知识(8)
  英语(1)
   相册
  java学习相关
  other
  好友照片
  日历
  流逝的青春
  设计模式相关
  走走拍拍
   关注blog
  atomic_age
  BeanSoft
  echoheart2008
  JAVA-HE
  kenzhang
  坏男孩
  干儿子——子源
  施伟
  蚂蚁
  鼠标
   积分与排名
  积分 - 161979
  排名 - 32
   最新评论
  1.?re: ajax学习笔记----一个初步的ajax开发框架
  我最近正在研究DWR,真的很不错.需要学习!!
  --baidw
  2.?re: 通用权限管理系统设计篇(三)——概要设计说明书
  学习呀,真是高!!
  希望有时间多向你学习!!!
  --baidw
  3.?re: 异常备忘:java.lang.UnsupportedClassVersionError: Bad version number in .class file[未登录]
  3Q
  --kelly
  4.?re: 使用XFire+Spring构建Web Service(二)
  哪位大哥大姐 也发一份资料给我吧 lele_love_lomboz@hotmail.com
  致谢
  --zhaoyl
  5.?re: 使用XFire+Spring构建Web Service(一)——helloWorld篇
  为什么我按照你的步骤建工程的时候怎么就没有xfire-servlet。xml这个文件呢?
  --jackie
   评论排行榜

本文转自
http://www.blogjava.net/amigoxie/archive/2007/08/16/137413.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值