




已阅读5页,还剩51页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
.,1,Java网络编程精解,作者:孙卫琴参考书籍:技术支持网址:,.,2,第8章基于UDP的数据报和套接字,参考Java网络编程精解的第8章,8.1UDP协议简介8.2DatagramPacket类8.3DatagramSocket类8.4DatagramChannel类8.5组播Socket,.,3,第8章基于UDP的数据报和套接字,UDP(UserDatagramProtocol,用户数据报协议)是传输层的另一种协议,它比TCP具有更快的传输速度,但是不可靠。UDP发送的数据单元称为UDP数据报。当网络传输UDP数据报时,无法保证数据报一定到达目的地,也无法保证各个数据报按发送的顺序到达目的地。当发送方先发送包含字符串“hello”的数据报,再发送包含字符串“everyone”的数据报,接收方有可能先接收到字符串“everyone”,再接收到字符串“hello”;也有可能什么数据也没有接收到,因为发送方发送的数据有可能在传输途中都丢失了。,.,4,8.1UDP协议简介,在Java中,java.util.DatagramSocket负责接收和发送UDP数据报,java.util.DatagramPacket表示UDP数据报。如图8-1所示,每个DatagramSocket与一个本地地址(包括本地主机的IP地址和本地UDP端口)绑定,每个DatagramSocket可以把UDP数据报发送给任意一个远程DatagramSocket,也可以接收来自任意一个远程DatagramSocket的UDP数据报。在UDP数据报中包含了目的地址的信息,DatagramSocket根据该信息把数据报发送到目的地。,.,5,8.1UDP协议简介,UDP协议是无连接的协议,客户端的DatagramSocket与服务器端的DatagramSocket不存在一一对应关系,两者无需建立连接,就能交换数据报。DatagramSocket提供了接收和发送数据报的方法:publicvoidreceive(DatagramPacketdst)throwsIOException/接收数据报publicvoidsend(DatagramPacketsrc)throwsIOException/发送数据报,.,6,8.1UDP协议简介,例程8-1的EchoServer与例程8-2的EchoClient就利用DatagramSocket来发送和接收数据报。同一时刻,可能会有多个EchoClient进程与EchoServer进程通信。EchoServer的DatagramSocket与UDP端口8000绑定,EchoClient则与任意一个可用的UDP端口绑定。EchoServer在一个while循环中不断接收EchoClient的数据报,然后给EchoClient回复一个数据报。EchoClient从控制台读取用户输入的字符串,把它包装成一个数据报,再把它发送给EchoServer,接着再接收EchoServer的响应数据报。,.,7,8.2DatagramPacket类,DatagramPacket表示数据报,它的构造方法可以分为两类:一类构造方法创建的DatagramPacket对象用来接收数据还有一类构造方法创建的DatagramPacket对象用来发送数据。两类构造方法的主要区别是,用于发送数据的构造方法需要设定数据报到达的目的地址,而用于接收数据的构造方法无需设定地址。,.,8,8.2DatagramPacket类,用于接收数据的构造方法包括:publicDatagramPacket(bytedata,intlength)publicDatagramPacket(bytedata,intoffset,intlength)以上data参数用来存放接收到的数据,参数length指定要接收的字节数,参数offset指定在data中存放数据的起始位置,即dataoffset。如果没有设定参数offset,那么起始位置为data0。,.,9,8.2DatagramPacket类,用于发送数据的构造方法包括:publicDatagramPacket(bytedata,intoffset,intlength,InetAddressaddress,intport)publicDatagramPacket(bytedata,intoffset,intlength,SocketAddressaddress)publicDatagramPacket(bytedata,intlength,InetAddressaddress,intport)publicDatagramPacket(bytedata,intlength,SocketAddressaddress)以上data参数中存放了要发送的数据,参数length指定要发送的字节数,参数offset指定要发送的数据在data中的起始位置,即dataoffset。如果没有设定参数offset,那么起始位置为data0。,.,10,8.2DatagramPacket类,以下两段程序代码都创建了一个数据报,它的送达地址为主机“myhost”的UDP端口100:InetAddressremoteIP=InetAddress.getByName(myhost);intremotePort=100;bytedata=hello.getBytes();/获得字符串“hello”的字符编码DatagramPacketoutputPacket=newDatagramPacket(data,data.length,remoteIP,remotePort);或者:InetAddressremoteIP=InetAddress.getByName(myhost);intremotePort=100;SocketAddressremoteAddr=newInetSocketAddress(remoteIP,remotePort);bytedata=hello.getBytes();DatagramPacketoutputPacket=newDatagramPacket(data,data.length,remoteAddr);,.,11,8.2.1选择数据报的大小,DatagramPacket的构造方法有一个参数length,它决定了要接收或发送的数据报的长度。对于用于接收数据的DatagramPacket,如果实际接收到的数据报的长度大于DatagramPacket的长度,那么多余的数据就会被丢弃。因此,必须为DatagramPacket选择合适的长度。理论上,IPv4数据报的最大长度为65507个字节,如果一个DatagramPacket的长度为65507个字节,那么它就可以接收任何IPv4数据报,而不会丢失数据。理论上,IPv6数据报的最大长度为65536字节。,.,12,8.2.1选择数据报的大小,选择数据报大小的通用原则是:如果网络非常不可靠,如分组无线电网络,则要选择较小的数据报,以减少传输中遭破坏的可能性。如果网络非常可靠,而且传输速度很快,就应当尽可能使用大的数据报。对于多数网络,8K是一个很好的折衷方案。,.,13,8.2.2读取和设置DatagramPacket的属性,DatagramPacket类包括以下属性:data:表示数据报的数据缓冲区。offset:表示数据报的数据缓冲区的起始位置。length:表示数据报的长度。address:对于用于发送的数据报,address属性表示数据报的目标地址。对于用于接收的数据报,address属性表示发送者的地址。port:对于用于发送的数据报,address属性表示数据报的目标UDP端口。对于用于接收的数据报,port属性表示接收者的UDP端口。,.,14,8.2.2读取和设置DatagramPacket的属性,DatagramPacket类提供了一系列get方法,用于读取各种属性:publicInetAddressgetAddress()publicintport()publicScoketAddressgetSocketAddress()publicbytegetData()publicintgetLength()publicintgetOffset(),.,15,8.2.2读取和设置DatagramPacket的属性,DatagramPacket类提供了一系列set方法,用于设置各种属性:publicvoidsetAddress(InetAddressaddr)publicvoidsetPort(intport)publicvoidsetSocketAddress(SocketAddressaddress)publicvoidsetData(bytedata)publicvoidsetData(bytedata,intoffset,intlength)publicvoidsetLength(intlength),.,16,8.2.3数据格式的转换,数据报中只能存放字节形式的数据。在发送方,需要把其他格式的数据转换为字节序列。在接收方,需要把字节序列转换为原来格式的数据。,.,17,8.2.3数据格式的转换,在发送方,可以利用ByteArrayOutputStream和DataOuputStream来把其他格式的数据转换为字节序列。例如以下longToByte()方法把long型数组中的数据转换为字节,把它们存放到一个字节数组中,再将其返回:publicbytelongToByte(longdata)throwsIOExceptionByteArrayOutputStreambao=newByteArrayOutputStream();DataOutputStreamdos=newDataOutputStream(bao);for(inti=0;idata.length;i+)dos.writeLong(datai);dos.close();returnbao.toByteArray();,.,18,8.2.3数据格式的转换,在接收方,可以利用ByteArrayInputStream和DataInputStream来把字节序列转换为原来格式的数据。例如以下byteToLong()方法把byte数组中的字节转换为long型数据,把它存放到一个long型数组中,再将其返回:publiclongbyteToLong(bytedata)throwsIOExceptionlongresult=newlongdata.length/8;/一个long数据占8个字节ByteArrayInputStreambai=newByteArrayInputStream(data);DataInputStreamdis=newDataInputStream(bai);for(inti=0;idata.length/8;i+)resulti=dis.readLong();returnresult;,.,19,8.2.4重用DatagramPacket,同一个DatagramPacket对象可以被重用,用来多次发送或接收数据。在例程8-3的DatagramTester类中,创建了sender和receiver两个线程。sender线程负责发送数据,这段操作由send()方法实现。Receiver线程负责接收数据,这段操作由receive()方法实现。,.,20,8.3DatagramSocket类,DatagramSocket负责接收和发送数据报。每个DatagramSocket对象都会与一个本地端口绑定,在此端口监听发送过来的数据报。在客户程序中,一般由操作系统为DatagramSocket分配本地端口,这种端口也称为匿名端口;在服务器程序中,一般由程序显式的为DatagramSocket指定本地端口。,.,21,8.3.1构造DatagramSocket,DatagramSocket的构造方法有以下几种重载形式:(1)DatagramSocket()(2)DatagramSocket(intport)(3)DatagramSocket(intport,InetAddressladdr)(4)DatagramSocket(SocketAddressbindaddr),.,22,8.3.1构造DatagramSocket,如果想知道一个DatagramSocket对象所绑定的本地地址,可以调用它的以下方法:intgetLocalPort():返回DatagramSocket所绑定的端口。InetAddressgetLocalAddress():返回DatagramSocket所绑定的IP地址。SocketAddressgetLocalSocketAddress():返回一个SocketAddress对象,它包含DatagramSocket所绑定的IP地址和端口信息。,.,23,8.3.2接收和发送数据报,DatagramSocket的send()方法负责发送一个数据报,该方法的定义如下:publicvoidsend(DatagramPacketdp)throwsIOException值得注意的是,UDP协议提供不可靠的传输,如果数据报没有到达目的地,send()方法不会抛出任何异常,因此发送方程序无法知道数据报是否被接收方接收到,除非双方通过应用层的特定协议来确保接收方未收到数据报时,发送方能重发数据报。,.,24,8.3.2接收和发送数据报,DatagramSocket的receive()方法负责接收一个数据报,该方法的定义如下:publicvoidreceive(DatagramPacketdatagramPacket)throwsIOException此方法从网络上接收一个数据报。如果网络上没有数据报,执行该方法的线程会进入阻塞状态,直到收到数据报为止。,.,25,8.3.3管理连接,两个TCPSocket之间存在固定的连接关系,而一个DatagramSocket可以与其他任意一个DatagramSocket交换数据报。在某些场合,一个DatagramSocket可能只希望与固定的另一个远程DatagramSocket通信。例如NFS客户只接收来自与之通信的服务器的数据报,再例如在网络游戏中,一个游戏网家只接收他的游戏搭档的数据报。,.,26,8.3.3管理连接,从JDK1.2开始,DatagramSocket添加了一些方法,利用这些方法,可以使一个DatagramSocket只能与另一个固定的DatagramSocket交换数据报:(1)publicvoidconnect(InetAddresshost,intport)(2)publicvoiddisconnect()(3)publicintgetPort()(4)publicInetAddressgetInetAddress()(5)publicSocketAddressgetRemoteSocketAddress(),.,27,8.3.4关闭DatagramSocket,DatagramSocket的close()方法会释放所占用的本地UDP端口。在程序中及时关闭不再需要的DatagramSocket,这是好的编程习惯。,.,28,8.3.5DatagramSocket的选项,DatagramSocket有以下选项:SO_TIMEOUT:表示接收数据报时的等待超时时间。SO_RCVBUF:表示接收数据的缓冲区的大小。SO_SNDBUF:表示发送数据的缓冲区的大小。SO_REUSEADDR:表示是否允许重用DatagramSocket所绑定的本地地址。SO_BROADCAST:表示是否允许对网络广播地址收发数据报。,.,29,8.4DatagramChannel类,从JDK1.4开始,添加了一个支持按照非阻塞方式发送和接收数据报的DatagramChannel。DatagramChannel是SelectableChannel的子类,可以注册到一个Selector。使用DatagramChannel,可以使得UDP服务器只需用单个线程就能同时与多个客户通信。DatagramChannel默认情况下采用阻塞模式,如果希望该为非阻塞模式,可以调用configureBlocking(false)方法。,.,30,8.4.1创建DatagramChannel,DatagramChannel类的静态open()方法返回一个DatagramChannel对象,每个DatagramChannel对象都关联了一个DatagramSocket对象,DatagramChannel对象的socket()方法返回这个DatagramSocket对象。DatagramChannel对象创建后,与它关联的DatagramSocket对象还没有绑定到任何地址,必须调用DatagramSocket对象的bind()方法来与一个本地地址绑定:DatagramChannelchannel=DatagramChannel.open();DatagramSocketsocket=channel.socket();SocketAddressaddress=newInetSocketAddress(8000);socket.bind(address);,.,31,8.4.2管理连接,与DatagramSocket一样,DatagramChannel的connect(SocketAddressremote)方法使得通道只能对特定的远程地址收发数据报。DatagramChannel的isConnected()方法判断通道是否只能对特定的远程地址收发数据报。只要调用DatagramChannel的disconnect()方法,就能使得通道能再次对多个远程地址收发数据报。UDP客户程序通常只和特定的UDP服务器通信,因此可在UDP客户程序中可以把DatagramChannel与远程服务器连接。UDP服务器需要与多个UDP客户程序通信,因此在UDP服务器中一般不用对DatagramChannel进行连接。,.,32,8.4.3用send()方法发送数据报,DatagramChannel的send(ByteBuffersrc,SocketAddresstarget)方法把参数src中的剩余数据作为一个数据报写到通道中,参数target指定目标地址,该方法返回发送的字节数:publicintsend(ByteBuffersrc,SocketAddresstarget)throwsIOException如果希望把相同数据发给多个客户,可以重用源ByteBuffer。在这种情况下,每次都要把ByteBuffer的位置重新设为零:channel.send(src,target1);src.rewind();/把缓冲区的位置重设为零channel.send(src,target2);src.rewind();/把缓冲区的位置重设为零channel.send(src,target3);,.,33,8.4.4用receive()方法接收数据报,DatagramChannel的receive(ByteBufferdst)方法从通道中读取一个数据报,存放在参数指定的ByteBuffer中,并返回数据报的发送方的地址:publicSocketAddressreceive(ByteBufferdst)throwsIOException如果DatagramChannel工作于阻塞模式,那么receive()方法在读取到数据报之前不会返回。如果DatagramChannel工作于非阻塞模式,那么receive()方法在没有数据报可读取的情况下立即返回null。,.,34,8.4.4用receive()方法接收数据报,例程8-4的SendChannel和例程8-5的ReceiveChannel分别发送和接收数据报。SendChannel工作于默认的阻塞模式,每次发送的数据报的长度为1024个字节。ReceiveChannel既可以工作于阻塞模式,也可以工作于非阻塞模式,ReceiveChannel的用来存放接收到的数据报的缓冲区buffer的大小既可以为1024个字节,也可以为4个字节,这都取决于运行ReceiveChannel时设置的命令行参数。,.,35,8.4.5用write()方法发送数据报,write()方法和send()方法一样,也能发送数据报。write()方法有三种重载形式:(1)publicintwrite(ByteBuffersrc)throwsIOException(2)publiclongwrite(ByteBuffersrcs)throwsIOException(3)publiclongwrite(ByteBuffersrcs,intoffset,intlength)throwsIOException,.,36,8.4.5用write()方法发送数据报,DatagramChannel的write()与send()方法的区别在于:(1)write()方法要求DatagramChannel已经建立连接,也就是说,程序在调用DatagramChannel的write()方法之前,要求先调用connect()方法使通道与特定的远程接收方连接。而send()方法则没有这一限制。(2)在非阻塞模式下,write()方法不保证把ByteBuffer内的所有剩余数据作为一个数据报发送。假如ByteBuffer的剩余数据为r,实际发送的字节数为n,那么0=n=r。而send()方法总是把ByteBuffer内的所有剩余数据作为一个数据报发送。,.,37,8.4.6用read()方法接收数据报,read()方法和receive()方法一样,也能接收数据报。read()方法有三种重载形式:publicintread(ByteBuffersrc)throwsIOExceptionpubliclongread(ByteBuffersrcs)throwsIOExceptionpubliclongread(ByteBuffersrcs,intoffset,intlength)throwsIOException,.,38,8.4.6用read()方法接收数据报,DatagramChannel的read()与receive()方法的区别在于:read()方法要求DatagramChannel已经建立连接,也就是说,程序在调用DatagramChannel的read()方法之前,要求先调用connect()方法使通道与特定的远程发送方连接。而receive()方法则没有这一限制。,.,39,8.4.6用read()方法接收数据报,例程8-7的EchoClient使用DatagramChannel与EchoServer通信。EchoClient类共使用了两个线程:主线程和Receiver线程。主线程主要负责接收和发送数据,这些操作由talk()方法实现。Receiver线程负责读取用户向控制台输入的数据,该操作由receiveFromUser()方法实现。,.,40,8.5组播Socket,网络数据传播按照接收者的数量,可分为以下三种方式:单播:提供点对点的通信。广播:发送者每次发送的数据可以被传播范围内的所有接收者接收。组播:发送者每次发送的数据可以被小组内的所有接收者接收。,.,41,8.5组播Socket,组播组内的所有主机共享同一个地址,这种地址称为组播地址。组播地址是范围在55之间的IP地址。此范围内的所有地址的前4个二进制位都是“1110”。组播地址也被称为D类IP地址,与其他的A类、B类和C类地址相区别。组播组是开放的,主机可以在任何时候进入或离开组。IANA(InternetAssignedNumbersAuthority)组织负责分发永久组播地址。,.,42,8.5组播Socket,组播与单播UDP的区别在于,前者必须考虑TTL(TimeToLive)值,它用IP数据包的头部的一个字节表示。TTL通过限制IP包被丢弃前通过的路由器数目,来决定IP包的生存时间。IP包每通过一个路由器,TTL就减一,当TTL变为0,这个包就被丢弃。TTL的一个作用是防止配置有误的路由器把包在路由器之间无限的来回传递,还有一个作用是限制组播的地理范围。,.,43,8.5.1MulticastSocket类,.MulticastSocket具有组播的功能,它是DatagramSocket的子类:publicclassMulticastSocketextendsDatagramSocket和DatagramSocket一样,MulticastSocket也与DatagramPacket搭配使用,DatagramPacket用来存放接收和发送的组播数据报。,.,44,8.5.1MulticastSocket类,如果要接收组播数据报,只需创建一个MulticastSocket,把它加入到组播组,就能接收发送到该组的组播数据。发送组播数据报与发送单播数据报非常相似,只需创建一个MulticastSocket,无需把它加入到组播组(当然也可以把它加入到组播组),就能向一个组播组发送数,.,45,8.5.1MulticastSocket类,1构造MulticastSocketMulticastSocket有以下构造方法:(1)publicMulticastSocket()throwsSocketException(2)publicMulticastSocket(intport)throwsSocketException(3)publicMulticastSocket(SocketAddressbindAddress)throwsSocketException,.,46,8.5.1MulticastSocket类,2与组播组通信MulticastSocket支持以下四种操作:(1)加入到组播组:joinGroup()方法(2)向组中成员发送数据报:send()方法(3)接收发送到组播组的数据报:receive()方法(4)离开组播组:leaveGroup()方法,.,47,8.5.1MulticastSocket类,3设置和获得MulticastSocket的属性MuliticastSocket类提供了两组用于设置和读取网络接口的方法。MuliticastSocket只会对该网络接口中的组收发组播数据:/第1组方法publicvoidsetInterface(InetAddressaddress)throwsSocketExceptionpublicInetAddressgetInterface()throwsSocketException/第2组方法publicvoidsetNetworkInterface(NetworkInterfaceinterface)throwsSocketExceptionpublicNetworkInterfacegetNetworkInterface()throwsSocketException,.,48,8.5.2组播Socket的范例,例程8-8的MulticastSender类向一个IP地址为的组播组发送数据报。MulticastSocket发送数据报的方式与DatagramSocket非常相似:DatagramPacketdp=newDatagramPacket(buffer,buffer.length,group,port);ms.send(dp);/发送组播数据报MulticastSocket不管是否加入到组播组,都能发送组播数据报。因此把程序中的“ms.joinGroup(group);”这一行注释掉,不会影响程序的运行效果。,.,49,8.5.2组播Socket的范例,在例程8-9的MulticastReceiver类中,MulticastSocket加入到IP地址为的组播组,然后不断接收发往该组的数据报。MulticastSocket接收数据报的方式与DatagramSocket非常相似:DatagramPacketdp=newDatagramPacket(buffer,buffer.length);ms.receive(dp);/接收组播数据报,.,50,练习题1,问题:以下哪些叙述是正确的?选项:a)DatagramSocket的send(DatagramPacketsrc)方法发送数据报时,如果无法送达接收方,该方法会抛出IOException。b)UDP协议是无连接的协议。c)对于用于接收数据的DatagramPacket,如果实际接收到的数据报的长度大于DatagramPacket的长度,那么多余的数据就会被丢弃。d)DatagramSocket的getInputStream()方法用于获得输入流。答案:b,c,.,51,练习题2,问题:以下是DatagramPacket的构造方法,哪些用于发送数据报?选项:a)publicDatagramPacket(bytedata,intlength)b)publicDatagramPacket(bytedata,intoffs
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年电子产品销售代理合同
- 2025年集体土地征收补偿合同范本
- 三大行书及其特点
- 2025年专利技术许可合同范本
- 2025年深度剖析合同履行争议案例
- 风电行业2025年技术创新在风电场环境保护中的应用报告
- 社区安保服务终止合同及公共秩序维护协议
- 2025年四川省农村土地经营权流转合同样本格式
- 2024-2025年新能源储能行业储能电站项目施工与验收标准分析报告
- 工业互联网平台数字签名技术规范2025年工业互联网安全态势感知平台建设报告
- 数字化印花工艺智能化
- 成人鼻肠管的留置与维护
- 专题02 概率与统计解答题综合(解析版)
- MOOC 模拟电子电路实验-东南大学 中国大学慕课答案
- 多格列艾汀使用指南2024课件
- MOOC 创业基础-暨南大学 中国大学慕课答案
- (2024年)面神经炎课件完整版
- GB/T 41666.4-2024地下无压排水管网非开挖修复用塑料管道系统第4部分:原位固化内衬法
- 云端药历健保署电子病历-慈济大学医学资讯学系
- 道路车辆 局域互联网络(LIN) 第3部分:协议规范
- 桩基工程施工总体部署
评论
0/150
提交评论