西安郵電大學(xué)Socket網(wǎng)絡(luò)編程_第1頁
西安郵電大學(xué)Socket網(wǎng)絡(luò)編程_第2頁
西安郵電大學(xué)Socket網(wǎng)絡(luò)編程_第3頁
西安郵電大學(xué)Socket網(wǎng)絡(luò)編程_第4頁
西安郵電大學(xué)Socket網(wǎng)絡(luò)編程_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、高級Internet實(shí)驗(yàn)報(bào)告 題目: Socket網(wǎng)絡(luò)編程 學(xué)生姓名: 班 級: 軟件1202班 學(xué) 號: 指導(dǎo)老師: 王文浪 成 績: 西安郵電大學(xué)計(jì)算機(jī)學(xué)院2015 年 4 月 27 日一、 實(shí)驗(yàn)?zāi)康?熟悉Socket網(wǎng)絡(luò)編程 熟悉CS客戶機(jī)模式 熟悉ServerSocket編寫服務(wù)端 熟悉使用多線程機(jī)制處理業(yè)務(wù) 了解客戶機(jī)之間通信方式二、 實(shí)驗(yàn)內(nèi)容及要求 采用CS模式,通過客戶機(jī)向服務(wù)器端發(fā)送消息; 采用Socket來實(shí)現(xiàn)客戶機(jī)之間的網(wǎng)絡(luò)通信; 通過ServerSocket創(chuàng)建服務(wù)端來處理接受客戶機(jī)請求; 通過多線程方式來處理客戶機(jī)之間的通信請求; 實(shí)現(xiàn)通信的界面窗口; 實(shí)驗(yàn)內(nèi)容有發(fā)送私

2、聊消息、向選中用戶發(fā)送文件、用戶接受文件。三、 實(shí)驗(yàn)過程 1.首先學(xué)習(xí)了在JAVA語言中TCP/IP協(xié)議下的Socket網(wǎng)絡(luò)模式圖如1.1所示 圖1.1TCP/IP協(xié)議下的Socket網(wǎng)絡(luò)模式圖由圖1.1可以得到,Socket通信的步驟如下:(1) 在服務(wù)器端創(chuàng)建一個(gè)ServerSocket對象并且指定端口號。(2) 運(yùn)行ServerSocket的accept()方法,等候客戶端的請求。(3) 客戶端創(chuàng)建一個(gè)Socket對象,指定計(jì)算機(jī)的地址和端口號,向服務(wù)器端發(fā)出連接請求。(4) 服務(wù)器端接收到來自客戶端的請求后,創(chuàng)建Socket對象與客戶端建立連接。(5) 服務(wù)器端和客戶端分別建立輸入輸出

3、流進(jìn)行數(shù)據(jù)傳輸。(6) 通信結(jié)束后,服務(wù)器端和客戶端分別關(guān)閉相應(yīng)的Socket連接。(7) 服務(wù)器端程序運(yùn)行結(jié)束后,調(diào)用ServerSocket對象的close()方法停止等待客戶端請求。 由此可以看出,對于一個(gè)網(wǎng)絡(luò)通信程序來說,需要編寫服務(wù)器端和客戶端兩個(gè)程序才能夠?qū)崿F(xiàn)相互通信,為了實(shí)現(xiàn)一個(gè)服務(wù)端程序能夠?qū)Χ鄠€(gè)客戶進(jìn)行服務(wù),需要使用到多線程,在服務(wù)器端創(chuàng)建客戶請求的監(jiān)聽線程,一旦客戶發(fā)起請求連接,在服務(wù)器端創(chuàng)建用于服務(wù)的Socket,利用改Socket完成與客戶的通信,即每個(gè)線程針對一個(gè)客戶進(jìn)行服務(wù),數(shù)據(jù)傳輸結(jié)束后,終止運(yùn)行該Socket通信的線程,繼續(xù)在服務(wù)器端指定的端口進(jìn)行監(jiān)聽。2. 數(shù)

4、據(jù)報(bào)的通信的發(fā)送和接收過程:應(yīng)用程序的工作流程如下:(1)首先要建立數(shù)據(jù)報(bào)通信的Socket,我們可以通過創(chuàng)建一個(gè)DatagramSocket對象實(shí)現(xiàn)它,在Java中DatagramSocket類有如下兩種構(gòu)造方法:public DatagramSocket() 構(gòu)造一個(gè)數(shù)據(jù)報(bào)socket,并使其與本地主機(jī)任一可用的端口連接。若打不開socket則拋出SocketException異常。public DatagramSocket(int port) 構(gòu)造一個(gè)數(shù)據(jù)報(bào)socket,并使其與本地主機(jī)指定的端口連接。若打不開socket或socket無法與指定的端口連接則拋出SocketExcepti

5、on異常。(2)創(chuàng)建一個(gè)數(shù)據(jù)報(bào)文包,用來實(shí)現(xiàn)無連接的包傳送服務(wù)。每個(gè)數(shù)據(jù)報(bào)文包用DatagramPacket類創(chuàng)建,DatagramPacket對象封裝了數(shù)據(jù)報(bào)包數(shù)據(jù)、包長度、目標(biāo)地址和目標(biāo)端口??蛻舳艘l(fā)送數(shù)據(jù)報(bào)文包,要調(diào)用DatagramPacket類以如下形式的構(gòu)造函數(shù)創(chuàng)建DatagramPacket對象,將要發(fā)送的數(shù)據(jù)和包文目的地址信息放入對象之中。DatagramPacket(byte bufferedarray,int length,InetAddress address,int port)即構(gòu)造一個(gè)包長度為length的包傳送到指定主機(jī)指定端口號上的數(shù)據(jù)報(bào)文包,參數(shù)length必

6、須小于等于bufferedarry.length。DatagramPacket類提供了4個(gè)類獲取信息:public byte getData() 返回一個(gè)字節(jié)數(shù)組,包含收到或要發(fā)送的數(shù)據(jù)報(bào)中的數(shù)據(jù)。public int getLength() 返回發(fā)送或接收到的數(shù)據(jù)的長度。public InetAddress getAddress() 返回一個(gè)發(fā)送或接收此數(shù)據(jù)報(bào)包文的機(jī)器的IP地址。public int getPort() 返回發(fā)送或接收數(shù)據(jù)報(bào)的遠(yuǎn)程主機(jī)的端口號。(3)創(chuàng)建完DatagramSocket和DatagramPacket對象,就可以發(fā)送數(shù)據(jù)報(bào)文包了。發(fā)送是通過調(diào)用DatagramS

7、ocket對象的send方法實(shí)現(xiàn),它需要以DatagramPacket對象為參數(shù),將剛才封裝進(jìn)DatagramPacket對象中的數(shù)據(jù)組成數(shù)據(jù)報(bào)發(fā)出。(4)當(dāng)然,我們也可以接收數(shù)據(jù)報(bào)文包。為了接收從服務(wù)器返回的結(jié)果數(shù)據(jù)報(bào)文包,我們需要?jiǎng)?chuàng)建一個(gè)新的DatagramPacket對象,這就需要用到DatagramPacket的另一種構(gòu)造方式DatagramPacket(byte bufferedarray,int length),即只需指明存放接收的數(shù)據(jù)報(bào)的緩沖區(qū)和長度。調(diào)用DatagramSocket對象的receive()方法完成接收數(shù)據(jù)報(bào)的工作,此時(shí)需要將上面創(chuàng)建的DatagramPacket

8、對象作為參數(shù),該方法會一直阻塞直到收到一個(gè)數(shù)據(jù)報(bào)文包,此時(shí)DatagramPacket的緩沖區(qū)中包含的就是接收到的數(shù)據(jù),數(shù)據(jù)報(bào)文包中也包含發(fā)送者的IP地址,發(fā)送者機(jī)器上的端口號等信息。(5)處理接收緩沖區(qū)內(nèi)的數(shù)據(jù),獲取服務(wù)結(jié)果。(6)當(dāng)通信完成后,可以使用DatagramSocket對象的close()方法關(guān)閉數(shù)據(jù)報(bào)通信Socket。當(dāng)然,Java會自動(dòng)關(guān)閉Socket,釋放DatagramSocket和DatagramPacket所占用的資源。但是作為一種良好的編程習(xí)慣,還是要顯式地予以關(guān)閉。3. DatagramSocket類詳解Java使用DatagramSocket代表UDP協(xié)議的So

9、cket,DatagramSocket本身只是碼頭,不能產(chǎn)生IO流,它的唯一作用就是接收和發(fā)送數(shù)據(jù)報(bào),Java使用DatagramPacket來代表數(shù)據(jù)報(bào),DatagramSocket接收和發(fā)送的數(shù)據(jù)都是通過DatagramPacket對象完成的。DatagramSocket():創(chuàng)建一個(gè)DatagramSocket實(shí)例,并將該對象綁定到本機(jī)默認(rèn)IP地址、本機(jī)所有可用端口中隨機(jī)選擇的某個(gè)端口。DatagramSocket(int prot):創(chuàng)建一個(gè)DatagramSocket實(shí)例,并將該對象綁定到本機(jī)默認(rèn)IP地址、指定端口。DatagramSocket(int port, InetAddre

10、ss laddr):創(chuàng)建一個(gè)DatagramSocket實(shí)例,并將該對象綁定到指定IP地址、指定端口。通過上面三個(gè)構(gòu)造器中的任意一個(gè)構(gòu)造器即可創(chuàng)建一個(gè)DatagramSocket實(shí)例,通常在創(chuàng)建服務(wù)器時(shí),創(chuàng)建指定端口的DatagramSocket實(shí)例-這樣保證其他客戶端可以將數(shù)據(jù)發(fā)送到該服務(wù)器。一旦得到了DatagramSocket實(shí)例之后,就可以通過如下兩個(gè)方法來接收和發(fā)送數(shù)據(jù)。receive(DatagramPacket p):從該DatagramSocket中接收數(shù)據(jù)報(bào)。send(DatagramPacket p):以該DatagramSocket對象向外發(fā)送數(shù)據(jù)報(bào)。從上面兩個(gè)方法可以看

11、出,使用DatagramSocket發(fā)送數(shù)據(jù)報(bào)時(shí),DatagramSocket并不知道將該數(shù)據(jù)報(bào)發(fā)送到哪里,而是由DatagramPacket自身決定數(shù)據(jù)報(bào)的目的地。就像碼頭并不知道每個(gè)集裝箱的目的地,碼頭只是將這些集裝箱發(fā)送出去,而集裝箱本身包含了該集裝箱的目的地。DatagramPacket的構(gòu)造器:DatagramPacket(byte buf,int length):以一個(gè)空數(shù)組來創(chuàng)建DatagramPacket對象,該對象的作用是接收DatagramSocket中的數(shù)據(jù)。DatagramPacket(byte buf, int length, InetAddress addr, in

12、t port):以一個(gè)包含數(shù)據(jù)的數(shù)組來創(chuàng)建DatagramPacket對象,創(chuàng)建該DatagramPacket對象時(shí)還指定了IP地址和端口-這就決定了該數(shù)據(jù)報(bào)的目的地。DatagramPacket(byte buf, int offset, int length):以一個(gè)空數(shù)組來創(chuàng)建DatagramPacket對象,并指定接收到的數(shù)據(jù)放入buf數(shù)組中時(shí)從offset開始,最多放length個(gè)字節(jié)。DatagramPacket(byte buf, int offset, int length, InetAddress address, int port):創(chuàng)建一個(gè)用于發(fā)送的DatagramPac

13、ket對象,指定發(fā)送buf數(shù)組中從offset開始,總共length個(gè)字節(jié)。當(dāng)Client/Server程序使用UDP協(xié)議時(shí),實(shí)際上并沒有明顯的服務(wù)器端和客戶端,因?yàn)閮煞蕉夹枰冉⒁粋€(gè)DatagramSocket對象,用來接收或發(fā)送數(shù)據(jù)報(bào),然后使用DatagramPacket對象作為傳輸數(shù)據(jù)的載體。通常固定IP地址、固定端口的DatagramSocket對象所在的程序被稱為服務(wù)器,因?yàn)樵揇atagramSocket可以主動(dòng)接收客戶端數(shù)據(jù)。在接收數(shù)據(jù)之前,應(yīng)該采用上面的第一個(gè)或第三個(gè)構(gòu)造器生成一個(gè)DatagramPacket對象,給出接收數(shù)據(jù)的字節(jié)數(shù)組及其長度。然后調(diào)用DatagramSock

14、et 的receive()方法等待數(shù)據(jù)報(bào)的到來,receive()將一直等待(該方法會阻塞調(diào)用該方法的線程),直到收到一個(gè)數(shù)據(jù)報(bào)為止。如下代碼所示:1. / 創(chuàng)建一個(gè)接收數(shù)據(jù)的DatagramPacket對象 2. DatagramPacket packet=new DatagramPacket(buf, 256); 3. / 接收數(shù)據(jù)報(bào) 4. socket.receive(packet); 在發(fā)送數(shù)據(jù)之前,調(diào)用第二個(gè)或第四個(gè)構(gòu)造器創(chuàng)建DatagramPacket對象,此時(shí)的字節(jié)數(shù)組里存放了想發(fā)送的數(shù)據(jù)。除此之外,還要給出完整的目的地址,包括IP地址和端口號。發(fā)送數(shù)據(jù)是通過DatagramSo

15、cket的send()方法實(shí)現(xiàn)的,send()方法根據(jù)數(shù)據(jù)報(bào)的目的地址來尋徑以傳送數(shù)據(jù)報(bào)。如下代碼所示:1. / 創(chuàng)建一個(gè)發(fā)送數(shù)據(jù)的DatagramPacket對象 2. DatagramPacket packet = new DatagramPacket(buf, length, address, port); 3. / 發(fā)送數(shù)據(jù)報(bào) 4. socket.send(packet); 使用DatagramPacket接收數(shù)據(jù)時(shí),會感覺DatagramPacket設(shè)計(jì)得過于煩瑣。開發(fā)者只關(guān)心該DatagramPacket能放多少數(shù)據(jù),而DatagramPacket是否采用字節(jié)數(shù)組來存儲數(shù)據(jù)完全不想

16、關(guān)心。但Java要求創(chuàng)建接收數(shù)據(jù)用的DatagramPacket時(shí),必須傳入一個(gè)空的字節(jié)數(shù)組,該數(shù)組的長度決定了該DatagramPacket能放多少數(shù)據(jù),這實(shí)際上暴露了DatagramPacket的實(shí)現(xiàn)細(xì)節(jié)。接著DatagramPacket又提供了一個(gè)getData()方法,該方法又可以返回Datagram Packet對象里封裝的字節(jié)數(shù)組,該方法更顯得有些多余-如果程序需要獲取DatagramPacket里封裝的字節(jié)數(shù)組,直接訪問傳給 DatagramPacket構(gòu)造器的字節(jié)數(shù)組實(shí)參即可,無須調(diào)用該方法。當(dāng)服務(wù)器端(也可以是客戶端)接收到一個(gè)DatagramPacket對象后,如果想向該數(shù)

17、據(jù)報(bào)的發(fā)送者反饋一些信息,但由于UDP協(xié)議是面向非連接的,所以接收者并不知道每個(gè)數(shù)據(jù)報(bào)由誰發(fā)送過來,但程序可以調(diào)用DatagramPacket的如下3個(gè)方法來獲取發(fā)送者的IP地址和端口。InetAddress getAddress():當(dāng)程序準(zhǔn)備發(fā)送此數(shù)據(jù)報(bào)時(shí),該方法返回此數(shù)據(jù)報(bào)的目標(biāo)機(jī)器的IP地址;當(dāng)程序剛接收到一個(gè)數(shù)據(jù)報(bào)時(shí),該方法返回該數(shù)據(jù)報(bào)的發(fā)送主機(jī)的IP地址。int getPort():當(dāng)程序準(zhǔn)備發(fā)送此數(shù)據(jù)報(bào)時(shí),該方法返回此數(shù)據(jù)報(bào)的目標(biāo)機(jī)器的端口;當(dāng)程序剛接收到一個(gè)數(shù)據(jù)報(bào)時(shí),該方法返回該數(shù)據(jù)報(bào)的發(fā)送主機(jī)的端口。SocketAddress getSocketAddress():當(dāng)程序準(zhǔn)備

18、發(fā)送此數(shù)據(jù)報(bào)時(shí),該方法返回此數(shù)據(jù)報(bào)的目標(biāo)SocketAddress;當(dāng)程序剛接收到一個(gè)數(shù)據(jù)報(bào)時(shí),該方法返回該數(shù)據(jù)報(bào)的發(fā)送主機(jī)的SocketAddress。getSocketAddress()方法的返回值是一個(gè)SocketAddress對象,該對象實(shí)際上就是一個(gè)IP地址和一個(gè)端口號。也就是說,SocketAddress對象封裝了一個(gè)InetAddress對象和一個(gè)代表端口的整數(shù),所以使用SocketAddress對象可以同時(shí)代表IP地址和端口。四測試結(jié)果四、 實(shí)驗(yàn)總結(jié) 本次實(shí)驗(yàn)過程總體比較順利,但是在客戶端,開始只聲明了一個(gè)DatagramPacket對象,即我在客戶端發(fā)送數(shù)據(jù),和接受數(shù)據(jù)時(shí),都只用這一個(gè)packet,開始認(rèn)為,接收到的新的packet會覆蓋掉原來的那個(gè),但是事實(shí)上是,收到的packet確實(shí)被收到的數(shù)據(jù)更新了,但是由于這個(gè)對象在內(nèi)存中的對象還是和發(fā)送是聲明的那個(gè)一樣,所以,如果客戶端發(fā)送三個(gè)字,而服務(wù)器恢復(fù)客戶端5個(gè)字,結(jié)果客戶端只能收到三個(gè)字,因?yàn)?,客戶端的packet在發(fā)送數(shù)據(jù)時(shí)就已經(jīng)確定了它發(fā)送和接受數(shù)據(jù)的長度,即三個(gè)字,所以導(dǎo)致,在客戶

溫馨提示

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

評論

0/150

提交評論