Java網(wǎng)絡(luò)編程精解PPT課件_第1頁(yè)
Java網(wǎng)絡(luò)編程精解PPT課件_第2頁(yè)
Java網(wǎng)絡(luò)編程精解PPT課件_第3頁(yè)
Java網(wǎng)絡(luò)編程精解PPT課件_第4頁(yè)
Java網(wǎng)絡(luò)編程精解PPT課件_第5頁(yè)
已閱讀5頁(yè),還剩51頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

.,1,Java網(wǎng)絡(luò)編程精解,作者:孫衛(wèi)琴參考書(shū)籍:技術(shù)支持網(wǎng)址:,.,2,第8章基于UDP的數(shù)據(jù)報(bào)和套接字,參考Java網(wǎng)絡(luò)編程精解的第8章,8.1UDP協(xié)議簡(jiǎn)介8.2DatagramPacket類(lèi)8.3DatagramSocket類(lèi)8.4DatagramChannel類(lèi)8.5組播Socket,.,3,第8章基于UDP的數(shù)據(jù)報(bào)和套接字,UDP(UserDatagramProtocol,用戶數(shù)據(jù)報(bào)協(xié)議)是傳輸層的另一種協(xié)議,它比TCP具有更快的傳輸速度,但是不可靠。UDP發(fā)送的數(shù)據(jù)單元稱為UDP數(shù)據(jù)報(bào)。當(dāng)網(wǎng)絡(luò)傳輸U(kuò)DP數(shù)據(jù)報(bào)時(shí),無(wú)法保證數(shù)據(jù)報(bào)一定到達(dá)目的地,也無(wú)法保證各個(gè)數(shù)據(jù)報(bào)按發(fā)送的順序到達(dá)目的地。當(dāng)發(fā)送方先發(fā)送包含字符串“hello”的數(shù)據(jù)報(bào),再發(fā)送包含字符串“everyone”的數(shù)據(jù)報(bào),接收方有可能先接收到字符串“everyone”,再接收到字符串“hello”;也有可能什么數(shù)據(jù)也沒(méi)有接收到,因?yàn)榘l(fā)送方發(fā)送的數(shù)據(jù)有可能在傳輸途中都丟失了。,.,4,8.1UDP協(xié)議簡(jiǎn)介,在Java中,java.util.DatagramSocket負(fù)責(zé)接收和發(fā)送UDP數(shù)據(jù)報(bào),java.util.DatagramPacket表示UDP數(shù)據(jù)報(bào)。如圖8-1所示,每個(gè)DatagramSocket與一個(gè)本地地址(包括本地主機(jī)的IP地址和本地UDP端口)綁定,每個(gè)DatagramSocket可以把UDP數(shù)據(jù)報(bào)發(fā)送給任意一個(gè)遠(yuǎn)程DatagramSocket,也可以接收來(lái)自任意一個(gè)遠(yuǎn)程DatagramSocket的UDP數(shù)據(jù)報(bào)。在UDP數(shù)據(jù)報(bào)中包含了目的地址的信息,DatagramSocket根據(jù)該信息把數(shù)據(jù)報(bào)發(fā)送到目的地。,.,5,8.1UDP協(xié)議簡(jiǎn)介,UDP協(xié)議是無(wú)連接的協(xié)議,客戶端的DatagramSocket與服務(wù)器端的DatagramSocket不存在一一對(duì)應(yīng)關(guān)系,兩者無(wú)需建立連接,就能交換數(shù)據(jù)報(bào)。DatagramSocket提供了接收和發(fā)送數(shù)據(jù)報(bào)的方法:publicvoidreceive(DatagramPacketdst)throwsIOException/接收數(shù)據(jù)報(bào)publicvoidsend(DatagramPacketsrc)throwsIOException/發(fā)送數(shù)據(jù)報(bào),.,6,8.1UDP協(xié)議簡(jiǎn)介,例程8-1的EchoServer與例程8-2的EchoClient就利用DatagramSocket來(lái)發(fā)送和接收數(shù)據(jù)報(bào)。同一時(shí)刻,可能會(huì)有多個(gè)EchoClient進(jìn)程與EchoServer進(jìn)程通信。EchoServer的DatagramSocket與UDP端口8000綁定,EchoClient則與任意一個(gè)可用的UDP端口綁定。EchoServer在一個(gè)while循環(huán)中不斷接收EchoClient的數(shù)據(jù)報(bào),然后給EchoClient回復(fù)一個(gè)數(shù)據(jù)報(bào)。EchoClient從控制臺(tái)讀取用戶輸入的字符串,把它包裝成一個(gè)數(shù)據(jù)報(bào),再把它發(fā)送給EchoServer,接著再接收EchoServer的響應(yīng)數(shù)據(jù)報(bào)。,.,7,8.2DatagramPacket類(lèi),DatagramPacket表示數(shù)據(jù)報(bào),它的構(gòu)造方法可以分為兩類(lèi):一類(lèi)構(gòu)造方法創(chuàng)建的DatagramPacket對(duì)象用來(lái)接收數(shù)據(jù)還有一類(lèi)構(gòu)造方法創(chuàng)建的DatagramPacket對(duì)象用來(lái)發(fā)送數(shù)據(jù)。兩類(lèi)構(gòu)造方法的主要區(qū)別是,用于發(fā)送數(shù)據(jù)的構(gòu)造方法需要設(shè)定數(shù)據(jù)報(bào)到達(dá)的目的地址,而用于接收數(shù)據(jù)的構(gòu)造方法無(wú)需設(shè)定地址。,.,8,8.2DatagramPacket類(lèi),用于接收數(shù)據(jù)的構(gòu)造方法包括:publicDatagramPacket(bytedata,intlength)publicDatagramPacket(bytedata,intoffset,intlength)以上data參數(shù)用來(lái)存放接收到的數(shù)據(jù),參數(shù)length指定要接收的字節(jié)數(shù),參數(shù)offset指定在data中存放數(shù)據(jù)的起始位置,即dataoffset。如果沒(méi)有設(shè)定參數(shù)offset,那么起始位置為data0。,.,9,8.2DatagramPacket類(lèi),用于發(fā)送數(shù)據(jù)的構(gòu)造方法包括:publicDatagramPacket(bytedata,intoffset,intlength,InetAddressaddress,intport)publicDatagramPacket(bytedata,intoffset,intlength,SocketAddressaddress)publicDatagramPacket(bytedata,intlength,InetAddressaddress,intport)publicDatagramPacket(bytedata,intlength,SocketAddressaddress)以上data參數(shù)中存放了要發(fā)送的數(shù)據(jù),參數(shù)length指定要發(fā)送的字節(jié)數(shù),參數(shù)offset指定要發(fā)送的數(shù)據(jù)在data中的起始位置,即dataoffset。如果沒(méi)有設(shè)定參數(shù)offset,那么起始位置為data0。,.,10,8.2DatagramPacket類(lèi),以下兩段程序代碼都創(chuàng)建了一個(gè)數(shù)據(jù)報(bào),它的送達(dá)地址為主機(jī)“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選擇數(shù)據(jù)報(bào)的大小,DatagramPacket的構(gòu)造方法有一個(gè)參數(shù)length,它決定了要接收或發(fā)送的數(shù)據(jù)報(bào)的長(zhǎng)度。對(duì)于用于接收數(shù)據(jù)的DatagramPacket,如果實(shí)際接收到的數(shù)據(jù)報(bào)的長(zhǎng)度大于DatagramPacket的長(zhǎng)度,那么多余的數(shù)據(jù)就會(huì)被丟棄。因此,必須為DatagramPacket選擇合適的長(zhǎng)度。理論上,IPv4數(shù)據(jù)報(bào)的最大長(zhǎng)度為65507個(gè)字節(jié),如果一個(gè)DatagramPacket的長(zhǎng)度為65507個(gè)字節(jié),那么它就可以接收任何IPv4數(shù)據(jù)報(bào),而不會(huì)丟失數(shù)據(jù)。理論上,IPv6數(shù)據(jù)報(bào)的最大長(zhǎng)度為65536字節(jié)。,.,12,8.2.1選擇數(shù)據(jù)報(bào)的大小,選擇數(shù)據(jù)報(bào)大小的通用原則是:如果網(wǎng)絡(luò)非常不可靠,如分組無(wú)線電網(wǎng)絡(luò),則要選擇較小的數(shù)據(jù)報(bào),以減少傳輸中遭破壞的可能性。如果網(wǎng)絡(luò)非??煽?,而且傳輸速度很快,就應(yīng)當(dāng)盡可能使用大的數(shù)據(jù)報(bào)。對(duì)于多數(shù)網(wǎng)絡(luò),8K是一個(gè)很好的折衷方案。,.,13,8.2.2讀取和設(shè)置DatagramPacket的屬性,DatagramPacket類(lèi)包括以下屬性:data:表示數(shù)據(jù)報(bào)的數(shù)據(jù)緩沖區(qū)。offset:表示數(shù)據(jù)報(bào)的數(shù)據(jù)緩沖區(qū)的起始位置。length:表示數(shù)據(jù)報(bào)的長(zhǎng)度。address:對(duì)于用于發(fā)送的數(shù)據(jù)報(bào),address屬性表示數(shù)據(jù)報(bào)的目標(biāo)地址。對(duì)于用于接收的數(shù)據(jù)報(bào),address屬性表示發(fā)送者的地址。port:對(duì)于用于發(fā)送的數(shù)據(jù)報(bào),address屬性表示數(shù)據(jù)報(bào)的目標(biāo)UDP端口。對(duì)于用于接收的數(shù)據(jù)報(bào),port屬性表示接收者的UDP端口。,.,14,8.2.2讀取和設(shè)置DatagramPacket的屬性,DatagramPacket類(lèi)提供了一系列g(shù)et方法,用于讀取各種屬性:publicInetAddressgetAddress()publicintport()publicScoketAddressgetSocketAddress()publicbytegetData()publicintgetLength()publicintgetOffset(),.,15,8.2.2讀取和設(shè)置DatagramPacket的屬性,DatagramPacket類(lèi)提供了一系列set方法,用于設(shè)置各種屬性:publicvoidsetAddress(InetAddressaddr)publicvoidsetPort(intport)publicvoidsetSocketAddress(SocketAddressaddress)publicvoidsetData(bytedata)publicvoidsetData(bytedata,intoffset,intlength)publicvoidsetLength(intlength),.,16,8.2.3數(shù)據(jù)格式的轉(zhuǎn)換,數(shù)據(jù)報(bào)中只能存放字節(jié)形式的數(shù)據(jù)。在發(fā)送方,需要把其他格式的數(shù)據(jù)轉(zhuǎn)換為字節(jié)序列。在接收方,需要把字節(jié)序列轉(zhuǎn)換為原來(lái)格式的數(shù)據(jù)。,.,17,8.2.3數(shù)據(jù)格式的轉(zhuǎn)換,在發(fā)送方,可以利用ByteArrayOutputStream和DataOuputStream來(lái)把其他格式的數(shù)據(jù)轉(zhuǎn)換為字節(jié)序列。例如以下longToByte()方法把long型數(shù)組中的數(shù)據(jù)轉(zhuǎn)換為字節(jié),把它們存放到一個(gè)字節(jié)數(shù)組中,再將其返回:publicbytelongToByte(longdata)throwsIOExceptionByteArrayOutputStreambao=newByteArrayOutputStream();DataOutputStreamdos=newDataOutputStream(bao);for(inti=0;idata.length;i+)dos.writeLong(datai);dos.close();returnbao.toByteArray();,.,18,8.2.3數(shù)據(jù)格式的轉(zhuǎn)換,在接收方,可以利用ByteArrayInputStream和DataInputStream來(lái)把字節(jié)序列轉(zhuǎn)換為原來(lái)格式的數(shù)據(jù)。例如以下byteToLong()方法把byte數(shù)組中的字節(jié)轉(zhuǎn)換為long型數(shù)據(jù),把它存放到一個(gè)long型數(shù)組中,再將其返回:publiclongbyteToLong(bytedata)throwsIOExceptionlongresult=newlongdata.length/8;/一個(gè)long數(shù)據(jù)占8個(gè)字節(jié)ByteArrayInputStreambai=newByteArrayInputStream(data);DataInputStreamdis=newDataInputStream(bai);for(inti=0;idata.length/8;i+)resulti=dis.readLong();returnresult;,.,19,8.2.4重用DatagramPacket,同一個(gè)DatagramPacket對(duì)象可以被重用,用來(lái)多次發(fā)送或接收數(shù)據(jù)。在例程8-3的DatagramTester類(lèi)中,創(chuàng)建了sender和receiver兩個(gè)線程。sender線程負(fù)責(zé)發(fā)送數(shù)據(jù),這段操作由send()方法實(shí)現(xiàn)。Receiver線程負(fù)責(zé)接收數(shù)據(jù),這段操作由receive()方法實(shí)現(xiàn)。,.,20,8.3DatagramSocket類(lèi),DatagramSocket負(fù)責(zé)接收和發(fā)送數(shù)據(jù)報(bào)。每個(gè)DatagramSocket對(duì)象都會(huì)與一個(gè)本地端口綁定,在此端口監(jiān)聽(tīng)發(fā)送過(guò)來(lái)的數(shù)據(jù)報(bào)。在客戶程序中,一般由操作系統(tǒng)為DatagramSocket分配本地端口,這種端口也稱為匿名端口;在服務(wù)器程序中,一般由程序顯式的為DatagramSocket指定本地端口。,.,21,8.3.1構(gòu)造DatagramSocket,DatagramSocket的構(gòu)造方法有以下幾種重載形式:(1)DatagramSocket()(2)DatagramSocket(intport)(3)DatagramSocket(intport,InetAddressladdr)(4)DatagramSocket(SocketAddressbindaddr),.,22,8.3.1構(gòu)造DatagramSocket,如果想知道一個(gè)DatagramSocket對(duì)象所綁定的本地地址,可以調(diào)用它的以下方法:intgetLocalPort():返回DatagramSocket所綁定的端口。InetAddressgetLocalAddress():返回DatagramSocket所綁定的IP地址。SocketAddressgetLocalSocketAddress():返回一個(gè)SocketAddress對(duì)象,它包含DatagramSocket所綁定的IP地址和端口信息。,.,23,8.3.2接收和發(fā)送數(shù)據(jù)報(bào),DatagramSocket的send()方法負(fù)責(zé)發(fā)送一個(gè)數(shù)據(jù)報(bào),該方法的定義如下:publicvoidsend(DatagramPacketdp)throwsIOException值得注意的是,UDP協(xié)議提供不可靠的傳輸,如果數(shù)據(jù)報(bào)沒(méi)有到達(dá)目的地,send()方法不會(huì)拋出任何異常,因此發(fā)送方程序無(wú)法知道數(shù)據(jù)報(bào)是否被接收方接收到,除非雙方通過(guò)應(yīng)用層的特定協(xié)議來(lái)確保接收方未收到數(shù)據(jù)報(bào)時(shí),發(fā)送方能重發(fā)數(shù)據(jù)報(bào)。,.,24,8.3.2接收和發(fā)送數(shù)據(jù)報(bào),DatagramSocket的receive()方法負(fù)責(zé)接收一個(gè)數(shù)據(jù)報(bào),該方法的定義如下:publicvoidreceive(DatagramPacketdatagramPacket)throwsIOException此方法從網(wǎng)絡(luò)上接收一個(gè)數(shù)據(jù)報(bào)。如果網(wǎng)絡(luò)上沒(méi)有數(shù)據(jù)報(bào),執(zhí)行該方法的線程會(huì)進(jìn)入阻塞狀態(tài),直到收到數(shù)據(jù)報(bào)為止。,.,25,8.3.3管理連接,兩個(gè)TCPSocket之間存在固定的連接關(guān)系,而一個(gè)DatagramSocket可以與其他任意一個(gè)DatagramSocket交換數(shù)據(jù)報(bào)。在某些場(chǎng)合,一個(gè)DatagramSocket可能只希望與固定的另一個(gè)遠(yuǎn)程DatagramSocket通信。例如NFS客戶只接收來(lái)自與之通信的服務(wù)器的數(shù)據(jù)報(bào),再例如在網(wǎng)絡(luò)游戲中,一個(gè)游戲網(wǎng)家只接收他的游戲搭檔的數(shù)據(jù)報(bào)。,.,26,8.3.3管理連接,從JDK1.2開(kāi)始,DatagramSocket添加了一些方法,利用這些方法,可以使一個(gè)DatagramSocket只能與另一個(gè)固定的DatagramSocket交換數(shù)據(jù)報(bào):(1)publicvoidconnect(InetAddresshost,intport)(2)publicvoiddisconnect()(3)publicintgetPort()(4)publicInetAddressgetInetAddress()(5)publicSocketAddressgetRemoteSocketAddress(),.,27,8.3.4關(guān)閉DatagramSocket,DatagramSocket的close()方法會(huì)釋放所占用的本地UDP端口。在程序中及時(shí)關(guān)閉不再需要的DatagramSocket,這是好的編程習(xí)慣。,.,28,8.3.5DatagramSocket的選項(xiàng),DatagramSocket有以下選項(xiàng):SO_TIMEOUT:表示接收數(shù)據(jù)報(bào)時(shí)的等待超時(shí)時(shí)間。SO_RCVBUF:表示接收數(shù)據(jù)的緩沖區(qū)的大小。SO_SNDBUF:表示發(fā)送數(shù)據(jù)的緩沖區(qū)的大小。SO_REUSEADDR:表示是否允許重用DatagramSocket所綁定的本地地址。SO_BROADCAST:表示是否允許對(duì)網(wǎng)絡(luò)廣播地址收發(fā)數(shù)據(jù)報(bào)。,.,29,8.4DatagramChannel類(lèi),從JDK1.4開(kāi)始,添加了一個(gè)支持按照非阻塞方式發(fā)送和接收數(shù)據(jù)報(bào)的DatagramChannel。DatagramChannel是SelectableChannel的子類(lèi),可以注冊(cè)到一個(gè)Selector。使用DatagramChannel,可以使得UDP服務(wù)器只需用單個(gè)線程就能同時(shí)與多個(gè)客戶通信。DatagramChannel默認(rèn)情況下采用阻塞模式,如果希望該為非阻塞模式,可以調(diào)用configureBlocking(false)方法。,.,30,8.4.1創(chuàng)建DatagramChannel,DatagramChannel類(lèi)的靜態(tài)open()方法返回一個(gè)DatagramChannel對(duì)象,每個(gè)DatagramChannel對(duì)象都關(guān)聯(lián)了一個(gè)DatagramSocket對(duì)象,DatagramChannel對(duì)象的socket()方法返回這個(gè)DatagramSocket對(duì)象。DatagramChannel對(duì)象創(chuàng)建后,與它關(guān)聯(lián)的DatagramSocket對(duì)象還沒(méi)有綁定到任何地址,必須調(diào)用DatagramSocket對(duì)象的bind()方法來(lái)與一個(gè)本地地址綁定:DatagramChannelchannel=DatagramChannel.open();DatagramSocketsocket=channel.socket();SocketAddressaddress=newInetSocketAddress(8000);socket.bind(address);,.,31,8.4.2管理連接,與DatagramSocket一樣,DatagramChannel的connect(SocketAddressremote)方法使得通道只能對(duì)特定的遠(yuǎn)程地址收發(fā)數(shù)據(jù)報(bào)。DatagramChannel的isConnected()方法判斷通道是否只能對(duì)特定的遠(yuǎn)程地址收發(fā)數(shù)據(jù)報(bào)。只要調(diào)用DatagramChannel的disconnect()方法,就能使得通道能再次對(duì)多個(gè)遠(yuǎn)程地址收發(fā)數(shù)據(jù)報(bào)。UDP客戶程序通常只和特定的UDP服務(wù)器通信,因此可在UDP客戶程序中可以把DatagramChannel與遠(yuǎn)程服務(wù)器連接。UDP服務(wù)器需要與多個(gè)UDP客戶程序通信,因此在UDP服務(wù)器中一般不用對(duì)DatagramChannel進(jìn)行連接。,.,32,8.4.3用send()方法發(fā)送數(shù)據(jù)報(bào),DatagramChannel的send(ByteBuffersrc,SocketAddresstarget)方法把參數(shù)src中的剩余數(shù)據(jù)作為一個(gè)數(shù)據(jù)報(bào)寫(xiě)到通道中,參數(shù)target指定目標(biāo)地址,該方法返回發(fā)送的字節(jié)數(shù):publicintsend(ByteBuffersrc,SocketAddresstarget)throwsIOException如果希望把相同數(shù)據(jù)發(fā)給多個(gè)客戶,可以重用源ByteBuffer。在這種情況下,每次都要把ByteBuffer的位置重新設(shè)為零:channel.send(src,target1);src.rewind();/把緩沖區(qū)的位置重設(shè)為零channel.send(src,target2);src.rewind();/把緩沖區(qū)的位置重設(shè)為零channel.send(src,target3);,.,33,8.4.4用receive()方法接收數(shù)據(jù)報(bào),DatagramChannel的receive(ByteBufferdst)方法從通道中讀取一個(gè)數(shù)據(jù)報(bào),存放在參數(shù)指定的ByteBuffer中,并返回?cái)?shù)據(jù)報(bào)的發(fā)送方的地址:publicSocketAddressreceive(ByteBufferdst)throwsIOException如果DatagramChannel工作于阻塞模式,那么receive()方法在讀取到數(shù)據(jù)報(bào)之前不會(huì)返回。如果DatagramChannel工作于非阻塞模式,那么receive()方法在沒(méi)有數(shù)據(jù)報(bào)可讀取的情況下立即返回null。,.,34,8.4.4用receive()方法接收數(shù)據(jù)報(bào),例程8-4的SendChannel和例程8-5的ReceiveChannel分別發(fā)送和接收數(shù)據(jù)報(bào)。SendChannel工作于默認(rèn)的阻塞模式,每次發(fā)送的數(shù)據(jù)報(bào)的長(zhǎng)度為1024個(gè)字節(jié)。ReceiveChannel既可以工作于阻塞模式,也可以工作于非阻塞模式,ReceiveChannel的用來(lái)存放接收到的數(shù)據(jù)報(bào)的緩沖區(qū)buffer的大小既可以為1024個(gè)字節(jié),也可以為4個(gè)字節(jié),這都取決于運(yùn)行ReceiveChannel時(shí)設(shè)置的命令行參數(shù)。,.,35,8.4.5用write()方法發(fā)送數(shù)據(jù)報(bào),write()方法和send()方法一樣,也能發(fā)送數(shù)據(jù)報(bào)。write()方法有三種重載形式:(1)publicintwrite(ByteBuffersrc)throwsIOException(2)publiclongwrite(ByteBuffersrcs)throwsIOException(3)publiclongwrite(ByteBuffersrcs,intoffset,intlength)throwsIOException,.,36,8.4.5用write()方法發(fā)送數(shù)據(jù)報(bào),DatagramChannel的write()與send()方法的區(qū)別在于:(1)write()方法要求DatagramChannel已經(jīng)建立連接,也就是說(shuō),程序在調(diào)用DatagramChannel的write()方法之前,要求先調(diào)用connect()方法使通道與特定的遠(yuǎn)程接收方連接。而send()方法則沒(méi)有這一限制。(2)在非阻塞模式下,write()方法不保證把ByteBuffer內(nèi)的所有剩余數(shù)據(jù)作為一個(gè)數(shù)據(jù)報(bào)發(fā)送。假如ByteBuffer的剩余數(shù)據(jù)為r,實(shí)際發(fā)送的字節(jié)數(shù)為n,那么0=n=r。而send()方法總是把ByteBuffer內(nèi)的所有剩余數(shù)據(jù)作為一個(gè)數(shù)據(jù)報(bào)發(fā)送。,.,37,8.4.6用read()方法接收數(shù)據(jù)報(bào),read()方法和receive()方法一樣,也能接收數(shù)據(jù)報(bào)。read()方法有三種重載形式:publicintread(ByteBuffersrc)throwsIOExceptionpubliclongread(ByteBuffersrcs)throwsIOExceptionpubliclongread(ByteBuffersrcs,intoffset,intlength)throwsIOException,.,38,8.4.6用read()方法接收數(shù)據(jù)報(bào),DatagramChannel的read()與receive()方法的區(qū)別在于:read()方法要求DatagramChannel已經(jīng)建立連接,也就是說(shuō),程序在調(diào)用DatagramChannel的read()方法之前,要求先調(diào)用connect()方法使通道與特定的遠(yuǎn)程發(fā)送方連接。而receive()方法則沒(méi)有這一限制。,.,39,8.4.6用read()方法接收數(shù)據(jù)報(bào),例程8-7的EchoClient使用DatagramChannel與EchoServer通信。EchoClient類(lèi)共使用了兩個(gè)線程:主線程和Receiver線程。主線程主要負(fù)責(zé)接收和發(fā)送數(shù)據(jù),這些操作由talk()方法實(shí)現(xiàn)。Receiver線程負(fù)責(zé)讀取用戶向控制臺(tái)輸入的數(shù)據(jù),該操作由receiveFromUser()方法實(shí)現(xiàn)。,.,40,8.5組播Socket,網(wǎng)絡(luò)數(shù)據(jù)傳播按照接收者的數(shù)量,可分為以下三種方式:?jiǎn)尾ィ禾峁c(diǎn)對(duì)點(diǎn)的通信。廣播:發(fā)送者每次發(fā)送的數(shù)據(jù)可以被傳播范圍內(nèi)的所有接收者接收。組播:發(fā)送者每次發(fā)送的數(shù)據(jù)可以被小組內(nèi)的所有接收者接收。,.,41,8.5組播Socket,組播組內(nèi)的所有主機(jī)共享同一個(gè)地址,這種地址稱為組播地址。組播地址是范圍在55之間的IP地址。此范圍內(nèi)的所有地址的前4個(gè)二進(jìn)制位都是“1110”。組播地址也被稱為D類(lèi)IP地址,與其他的A類(lèi)、B類(lèi)和C類(lèi)地址相區(qū)別。組播組是開(kāi)放的,主機(jī)可以在任何時(shí)候進(jìn)入或離開(kāi)組。IANA(InternetAssignedNumbersAuthority)組織負(fù)責(zé)分發(fā)永久組播地址。,.,42,8.5組播Socket,組播與單播UDP的區(qū)別在于,前者必須考慮TTL(TimeToLive)值,它用IP數(shù)據(jù)包的頭部的一個(gè)字節(jié)表示。TTL通過(guò)限制IP包被丟棄前通過(guò)的路由器數(shù)目,來(lái)決定IP包的生存時(shí)間。IP包每通過(guò)一個(gè)路由器,TTL就減一,當(dāng)TTL變?yōu)?,這個(gè)包就被丟棄。TTL的一個(gè)作用是防止配置有誤的路由器把包在路由器之間無(wú)限的來(lái)回傳遞,還有一個(gè)作用是限制組播的地理范圍。,.,43,8.5.1MulticastSocket類(lèi),.MulticastSocket具有組播的功能,它是DatagramSocket的子類(lèi):publicclassMulticastSocketextendsDatagramSocket和DatagramSocket一樣,MulticastSocket也與DatagramPacket搭配使用,DatagramPacket用來(lái)存放接收和發(fā)送的組播數(shù)據(jù)報(bào)。,.,44,8.5.1MulticastSocket類(lèi),如果要接收組播數(shù)據(jù)報(bào),只需創(chuàng)建一個(gè)MulticastSocket,把它加入到組播組,就能接收發(fā)送到該組的組播數(shù)據(jù)。發(fā)送組播數(shù)據(jù)報(bào)與發(fā)送單播數(shù)據(jù)報(bào)非常相似,只需創(chuàng)建一個(gè)MulticastSocket,無(wú)需把它加入到組播組(當(dāng)然也可以把它加入到組播組),就能向一個(gè)組播組發(fā)送數(shù),.,45,8.5.1MulticastSocket類(lèi),1構(gòu)造MulticastSocketMulticastSocket有以下構(gòu)造方法:(1)publicMulticastSocket()throwsSocketException(2)publicMulticastSocket(intport)throwsSocketException(3)publicMulticastSocket(SocketAddressbindAddress)throwsSocketException,.,46,8.5.1MulticastSocket類(lèi),2與組播組通信MulticastSocket支持以下四種操作:(1)加入到組播組:joinGroup()方法(2)向組中成員發(fā)送數(shù)據(jù)報(bào):send()方法(3)接收發(fā)送到組播組的數(shù)據(jù)報(bào):receive()方法(4)離開(kāi)組播組:leaveGroup()方法,.,47,8.5.1MulticastSocket類(lèi),3設(shè)置和獲得MulticastSocket的屬性MuliticastSocket類(lèi)提供了兩組用于設(shè)置和讀取網(wǎng)絡(luò)接口的方法。MuliticastSocket只會(huì)對(duì)該網(wǎng)絡(luò)接口中的組收發(fā)組播數(shù)據(jù):/第1組方法publicvoidsetInterface(InetAddressaddress)throwsSocketExceptionpublicInetAddressgetInterface()throwsSocketException/第2組方法publicvoidsetNetworkInterface(NetworkInterfaceinterface)throwsSocketExceptionpublicNetworkInterfacegetNetworkInterface()throwsSocketException,.,48,8.5.2組播Socket的范例,例程8-8的MulticastSender類(lèi)向一個(gè)IP地址為的組播組發(fā)送數(shù)據(jù)報(bào)。MulticastSocket發(fā)送數(shù)據(jù)報(bào)的方式與DatagramSocket非常相似:DatagramPacketdp=newDatagramPacket(buffer,buffer.length,group,port);ms.send(dp);/發(fā)送組播數(shù)據(jù)報(bào)MulticastSocket不管是否加入到組播組,都能發(fā)送組播數(shù)據(jù)報(bào)。因此把程序中的“ms.joinGroup(group);”這一行注釋掉,不會(huì)影響程序的運(yùn)行效果。,.,49,8.5.2組播Socket的范例,在例程8-9的MulticastReceiver類(lèi)中,MulticastSocket加入到IP地址為的組播組,然后不斷接收發(fā)往該組的數(shù)據(jù)報(bào)。MulticastSocket接收數(shù)據(jù)報(bào)的方式與DatagramSocket非常相似:DatagramPacketdp=newDatagramPacket(buffer,buffer.length);ms.receive(dp);/接收組播數(shù)據(jù)報(bào),.,50,練習(xí)題1,問(wèn)題:以下哪些敘述是正確的?選項(xiàng):a)DatagramSocket的send(DatagramPacketsrc)方法發(fā)送數(shù)據(jù)報(bào)時(shí),如果無(wú)法送達(dá)接收方,該方法會(huì)拋出IOException。b)UDP協(xié)議是無(wú)連接的協(xié)議。c)對(duì)于用于接收數(shù)據(jù)的DatagramPacket,如果實(shí)際接收到的數(shù)據(jù)報(bào)的長(zhǎng)度大于DatagramPacket的長(zhǎng)度,那么多余的數(shù)據(jù)就會(huì)被丟棄。d)DatagramSocket的getInputStream()方法用于獲得輸入流。答案:b,c,.,51,練習(xí)題2,問(wèn)題:以下是DatagramPacket的構(gòu)造方法,哪些用于發(fā)送數(shù)據(jù)報(bào)?選項(xiàng):a)publicDatagramPacket(bytedata,intlength)b)publicDatagramPacket(bytedata,intoffs

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論