Java UDP

来源:互联网 发布:刘德华唱功怎么样知乎 编辑:程序博客网 时间:2024/05/04 05:12
一. 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 QPING */  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      */      public final int getSoTimeout() throws Exception {          return ds.getSoTimeout();      }        /**      * 绑定监听地址和端口.      * @param host 主机IP      * @param port 端口      * @throws SocketException      */      public final void bind(String host, int port) throws SocketException {          socketAddress = new InetSocketAddress(host, port);          ds = new DatagramSocket(socketAddress);      }          /**      * 接收数据包,该方法会造成线程阻塞.      * @return 返回接收的数据串信息      * @throws IOException       */      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      */      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 缓冲长度      */      public final void setLength(int bufsize) {          packet.setLength(bufsize);      }        /**      * 获得发送回应的IP地址.      * @return 返回回应的IP地址      */      public final InetAddress getResponseAddress() {          return packet.getAddress();      }        /**      * 获得回应的主机的端口.      * @return 返回回应的主机的端口.      */      public final int getResponsePort() {          return packet.getPort();      }        /**      * 关闭udp监听口.      */      public final void close() {          try {              ds.close();          } catch (Exception ex) {              ex.printStackTrace();          }      }        /**      * 测试方法.      * @param args      * @throws Exception      */      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 QPING */  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      */      public final void setSoTimeout(final int timeout) throws Exception {          ds.setSoTimeout(timeout);      }        /**      * 获得超时时间.      * @return 返回超时时间      * @throws Exception      */      public final int getSoTimeout() throws Exception {          return ds.getSoTimeout();      }        public final DatagramSocket getSocket() {          return ds;      }        /**      * 向指定的服务端发送数据信息.      * @param host 服务器主机地址      * @param port 服务端端口      * @param bytes 发送的数据信息      * @return 返回构造后俄数据报      * @throws IOException      */      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      */      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连接.      */      public final void close() {          try {              ds.close();          } catch (Exception ex) {              ex.printStackTrace();          }      }        /**      * 测试客户端发包和接收回应信息的方法.      * @param args      * @throws Exception      */      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);      }  } 



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 武装突袭3受伤了怎么办 模板跟旺铺版本不符合怎么办 cpu散热硅胶没了怎么办 武装突袭3掉帧怎么办 苹果系统占用内存太大怎么办 电脑上的文件打不开怎么办 word文件打开是乱码怎么办 wps文件打开是乱码怎么办 电脑读tst文件乱码怎么办 智能手机中了勒索病毒怎么办 部队训练脚崴了怎么办 滴滴车型信息识别失败怎么办 先打人被打了怎么办 我被警察打了怎么办 2k13选秀卡住了怎么办 正当防卫二进去之后没有字怎么办 国土防线2子弹打完了怎么办 诛仙宠物满了怎么办 试用联盟认证手机号是空号怎么办 系统出新版本不显示更新怎么办 炉石账号封停怎么办 电脑用户名和密码忘了怎么办 黑猴子棒球1闪退怎么办 斗米兼职报名后怎么办 婴儿足跟血检查有异常怎么办 打印机显示脱机使用打印机怎么办 手机刷机后内存变小了怎么办 吃了解毒丹喝酒怎么办 6s更新ios11失败怎么办 苹果6s手机发热怎么办 苹果手机没有描述文件怎么办 电脑玩穿越火线卡怎么办 老电脑又卡又慢怎么办 梦幻之星4花屏怎么办 失业连续好多天睡不着觉怎么办 工业废气排放总量超标怎么办 lol美服更新不了怎么办 支付宝没法实名额度上限怎么办 苹果手机软件被禁止联网了怎么办 幽灵行动荒野黑屏怎么办打开游戏 幽灵行动荒野一点战役就秒退怎么办