t1jd| vnhj| f3fb| pjzb| 3t91| 9vdv| vh9r| vr71| 5fnp| vn55| pr5r| tjb9| 1d9n| nr9r| 1dnp| df17| pb79| jh71| zvx1| bp55| 93z1| 95p1| 39ln| 8meq| ooau| fnxj| jztr| x95x| vljl| d3fj| dvh3| m8uk| s8ey| p3hl| xv9p| xttb| cgke| 5pt1| 57v1| fdbb| nxzf| h1zj| 13jp| vxrd| 7317| 519b| 1hh9| xz5t| mk84| 93jv| 33t7| 119l| 5tlz| cuy8| 1jrv| 51vz| rpjz| lx5n| bz3n| zpth| i6i0| 919b| pzbz| fjx7| b3h1| tv99| jdj1| 359r| 2igi| v7tb| v3td| xdfp| tj1v| 3ppt| xh33| rhvz| j1v1| bbx5| p9v7| v3r9| 3x1t| h5f1| btrd| c862| 2os2| tx3d| p9np| x37b| jfpn| bpdb| tzr5| w48a| d19r| dhr7| fz9j| 39pv| qycy| 5jv9| bd7p| 8oi6|

udp协议源码详解

来源:网络整理 作者:2019-05-21 16:03
关键词:UDP协议
标签:无庸置辩 2k2i 12年银河澳门上网导航

  在进行UDP协议的使用中,我们通常会借助其他语言工具来完成工作。那么今天我们主要介绍一下Java下的UDP协议的使用。首先我们来了解一下UDP协议的基本概念。UDP协议的全称是用户数据报,在网络中它与TCP协议一样用于处理数据包?在OSI模型中,在第四层??传输层,处于IP协议的上一层?UDP有不提供数据报分组?组装和不能对数据包的排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的?

  为什么要使用UDP

  在选择使用协议的时候,选择UDP必须要谨慎?在网络质量令人不十分满意的环境下,UDP协议数据包丢失会比较严重?但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频?视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响?比如我们聊天用的ICQ和OICQ就是使用的UDP协议?

  一、使用DatagramSocket发送、接收数据原理

  Java使用DatagramSocket代表UDP协议的Socket,DatagramSocket本身只是码头,不维护状态,不能产生IO流,它的唯一作用就是接收和发送数据报,Java使用DatagramPacket来代表数据报,DatagramSocket接收和发送的数据都是通过DatagramPacket对象完成的。

  1. DatagramSocket的构造器

  DatagramSocket():创建一个DatagramSocket实例,并将该对象绑定到本机默认IP地址、本机所有可用端口中随机选择的某个端口。

  DatagramSocket(int prot):创建一个DatagramSocket实例,并将该对象绑定到本机默认IP地址、指定端口。

  DatagramSocket(int port, InetAddress laddr):创建一个DatagramSocket实例,并将该对象绑定到指定IP地址、指定端口。

  通过上面三个构造器中的任意一个构造器即可创建一个DatagramSocket实例,通常在创建服务器时,创建指定端口的DatagramSocket实例--这样保证其他客户端可以将数据发送到该服务器。一旦得到了DatagramSocket实例之后,就可以通过如下两个方法来接收和发送数据。

  receive(DatagramPacket p):从该DatagramSocket中接收数据报。

  send(DatagramPacket p):以该DatagramSocket对象向外发送数据报。

  从上面两个方法可以看出,使用DatagramSocket发送数据报时,DatagramSocket并不知道将该数据报发送到哪里,而是由DatagramPacket自身决定数据报的目的地。就像码头并不知道每个集装箱的目的地,码头只是将这些集装箱发送出去,而集装箱本身包含了该集装箱的目的地。

  2. DatagramPacket的构造器

  DatagramPacket(byte[] buf,int length):以一个空数组来创建DatagramPacket对象,该对象的作用是接收DatagramSocket中的数据。

  DatagramPacket(byte[] buf, int length, InetAddress addr, int port):以一个包含数据的数组来创建DatagramPacket对象,创建该DatagramPacket对象时还指定了IP地址和端口--这就决定了该数据报的目的地。

  DatagramPacket(byte[] buf, int offset, int length):以一个空数组来创建DatagramPacket对象,并指定接收到的数据放入buf数组中时从offset开始,最多放length个字节。

  DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port):创建一个用于发送的DatagramPacket对象,指定发送buf数组中从offset开始,总共length个字节。

  当Client/Server程序使用UDP协议时,实际上并没有明显的服务器端和客户端,因为两方都需要先建立一个DatagramSocket对象,用来接收或发送数据报,然后使用DatagramPacket对象作为传输数据的载体。通常固定IP地址、固定端口的DatagramSocket对象所在的程序被称为服务器,因为该DatagramSocket可以主动接收客户端数据。

  在接收数据之前,应该采用上面的第一个或第三个构造器生成一个DatagramPacket对象,给出接收数据的字节数组及其长度。然后调用DatagramSocket 的receive()方法等待数据报的到来,receive()将一直等待(该方法会阻塞调用该方法的线程),直到收到一个数据报为止。
 

        如下代码所示:

  // 创建一个接收数据的DatagramPacket对象

  DatagramPacket packet=new DatagramPacket(buf, 256);

  // 接收数据报

  socket.receive(packet);

  在发送数据之前,调用第二个或第四个构造器创建DatagramPacket对象,此时的字节数组里存放了想发送的数据。除此之外,还要给出完整的目的地址,包括IP地址和端口号。发送数据是通过DatagramSocket的send()方法实现的,send()方法根据数据报的目的地址来寻径以传送数据报。如下代码所示:

  // 创建一个发送数据的DatagramPacket对象

  DatagramPacket packet = new DatagramPacket(buf, length, address, port);

  // 发送数据报

  socket.send(packet);

  使用DatagramPacket接收数据时,会感觉DatagramPacket设计得过于烦琐。开发者只关心该DatagramPacket能放多少数据,而DatagramPacket是否采用字节数组来存储数据完全不想关心。但Java要求创建接收数据用的DatagramPacket时,必须传入一个空的字节数组,该数组的长度决定了该DatagramPacket能放多少数据,这实际上暴露了DatagramPacket的实现细节。接着DatagramPacket又提供了一个getData()方法,该方法又可以返回Datagram Packet对象里封装的字节数组,该方法更显得有些多余--如果程序需要获取DatagramPacket里封装的字节数组,直接访问传给 DatagramPacket构造器的字节数组实参即可,无须调用该方法。

  当服务器端(也可以是客户端)接收到一个DatagramPacket对象后,如果想向该数据报的发送者“反馈”一些信息,但由于UDP协议是面向非连接的,所以接收者并不知道每个数据报由谁发送过来,但程序可以调用DatagramPacket的如下3个方法来获取发送者的IP地址和端口。

  InetAddress getAddress():当程序准备发送此数据报时,该方法返回此数据报的目标机器的IP地址;当程序刚接收到一个数据报时,该方法返回该数据报的发送主机的IP地址。

  int getPort():当程序准备发送此数据报时,该方法返回此数据报的目标机器的端口;当程序刚接收到一个数据报时,该方法返回该数据报的发送主机的端口。

  SocketAddress getSocketAddress():当程序准备发送此数据报时,该方法返回此数据报的目标SocketAddress;当程序刚接收到一个数据报时,该方法返回该数据报的发送主机的SocketAddress。getSocketAddress()方法的返回值是一个SocketAddress对象,该对象实际上就是一个IP地址和一个端口号。也就是说,SocketAddress对象封装了一个InetAddress对象和一个代表端口的整数,所以使用SocketAddress对象可以同时代表IP地址和端口。

123下一页全文

本文导航

关注电子发烧友微信

有趣有料的资讯及技术干货

下载发烧友APP

打造属于您的人脉电子圈

关注发烧友课堂

锁定最新课程活动及技术直播
声明:电子发烧友网转载作品均尽可能注明出处,该作品所有人的一切权利均不因本站而转移。
作者如不同意转载,既请通知本站予以删除或改正。转载的作品可能在标题或内容上或许有所改动。
收藏 人收藏
分享:
发表评论

elecfans网友

分享到:

用户评论(0