国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

基于JavaSocket編程的網(wǎng)絡(luò)文件服務(wù)系統(tǒng)研究

2022-07-08 07:19李柯
電子技術(shù)與軟件工程 2022年2期
關(guān)鍵詞:空閑服務(wù)器端線程

李柯

(西北工業(yè)大學(xué) 陜西省西安市 710000)

1 基本介紹

實(shí)際上進(jìn)程之間的通信是通過(guò)向雙方的套接字發(fā)送報(bào)文(應(yīng)用程序交換信息分組)來(lái)實(shí)現(xiàn)的,進(jìn)程所在的應(yīng)用層通過(guò)套接字與運(yùn)輸層連接。根據(jù)使用的運(yùn)輸層協(xié)議不同,還可分為UDP套接字和TCP套接字。套接字充當(dāng)一個(gè)“運(yùn)輸和預(yù)處理者”,檢查運(yùn)輸層協(xié)議發(fā)來(lái)的報(bào)文并采取適當(dāng)?shù)膭?dòng)作。

集中式系統(tǒng)的部件(計(jì)算機(jī))局限在一個(gè)地方,使用限制很多,難以實(shí)現(xiàn)系統(tǒng)的拓展、設(shè)備的移動(dòng),缺乏靈活性和便捷性,且難以應(yīng)用在包括Web文檔系統(tǒng)、學(xué)習(xí)工作中的工作流系統(tǒng)等當(dāng)中。而對(duì)于分布式系統(tǒng),系統(tǒng)的部件(計(jì)算機(jī))不在同一地理位置,在物理上相互獨(dú)立,地位平等,但卻存在緊密的合作,用戶獲取資源時(shí)不需要知道資源在系統(tǒng)中的具體位置,分布式系統(tǒng)在用戶面前將呈現(xiàn)出一個(gè)單一的系統(tǒng)整體。其開(kāi)發(fā)、可擴(kuò)展、異構(gòu)、透明、安全的特點(diǎn),使分布式計(jì)算系統(tǒng)被用于許多不同類(lèi)型的應(yīng)用中,如共享存儲(chǔ)器多處理機(jī)。

2 基于TCP建立連接通訊、UDP傳輸數(shù)據(jù)的文件服務(wù)系統(tǒng)

于是我們是否能利用高級(jí)語(yǔ)言所提供的一些方法和代碼庫(kù),通過(guò)代碼的組織管理,實(shí)現(xiàn)利用TCP和UDP進(jìn)行多線程傳輸數(shù)據(jù)的系統(tǒng)。由于Java編程語(yǔ)言面向?qū)ο?、可移植性?qiáng)(Java在自己的虛擬機(jī)JVM上編譯運(yùn)行,JVM上具有完整的虛擬硬件系統(tǒng)和完整的指令系統(tǒng),使得Java程序在其他平臺(tái)上只要擁有JVM就能不加修改地運(yùn)行)、功能強(qiáng)大、操作簡(jiǎn)單,而且Java提供了多線程實(shí)現(xiàn)的類(lèi)與接口,使利用Java實(shí)現(xiàn)多線程系統(tǒng)變得相對(duì)更加簡(jiǎn)單。

想要實(shí)現(xiàn)在網(wǎng)絡(luò)中進(jìn)程之間通信,就要對(duì)每一個(gè)進(jìn)程賦予唯一標(biāo)識(shí)。網(wǎng)絡(luò)中的進(jìn)程需要利用網(wǎng)絡(luò)層的IP地址唯一標(biāo)識(shí)網(wǎng)絡(luò)中的主機(jī),傳輸層的所用協(xié)議和端口唯一標(biāo)識(shí)主機(jī)中的進(jìn)程。所以,形成了三元組(IP地址,協(xié)議,端口)來(lái)標(biāo)識(shí)網(wǎng)絡(luò)的進(jìn)程。進(jìn)程在網(wǎng)絡(luò)中的通信通過(guò)該三元組唯一標(biāo)識(shí)其它進(jìn)程并與之進(jìn)行交互。

2.1 建立服務(wù)器與客戶之間的TCP連接

服務(wù)器端指定一個(gè)空閑端口號(hào)創(chuàng)建一個(gè)ServerSocket實(shí)例,當(dāng)然該端口必須是空閑端口:服務(wù)器如果指定系統(tǒng)或者其它進(jìn)程已經(jīng)占用的端口,將會(huì)返回異常,只有和空閑端口連接才能正常運(yùn)行。選定空閑端口簡(jiǎn)單的方法是:1~1023已經(jīng)被系統(tǒng)占用,只有1024~65535之間的端口號(hào)為空閑端口,可供使用。比如HTTP協(xié)議一般使用80端口,當(dāng)然如要應(yīng)用HTTP協(xié)議,除了使用80端口,也可以使用其他的空閑端口實(shí)現(xiàn)HTTP協(xié)議。還可以使用端口掃描,通過(guò)創(chuàng)建以主機(jī)IP地址和測(cè)試端口號(hào)為構(gòu)造方法參數(shù)的socket對(duì)象,如果創(chuàng)建成功,便為空閑端口,如果拋出IO異常便為被占用端口。ServerSocket代表服務(wù)器端服務(wù)套接字,可以創(chuàng)建連接中屬于服務(wù)器端的socket實(shí)例。Socket代表客戶端套接字,與服務(wù)器端創(chuàng)建的socket實(shí)例建立連接。建立TCP連接時(shí),兩端socket將自動(dòng)完成TCP需要三次握手的過(guò)程。服務(wù)端同時(shí)運(yùn)行ServerSocket和與客戶建立連接的服務(wù)器端Socket,而客戶端只運(yùn)行客戶端Socket。ServerSocket以選定端口作為參數(shù),生成與選定端口連接的serverSocket對(duì)象;Socket通過(guò)默認(rèn)構(gòu)造方法創(chuàng)建一個(gè)與隨機(jī)可用端口綁定的流套接字,并通過(guò)connect方法以一個(gè)InetSocketAddress對(duì)象作為參數(shù)向服務(wù)器發(fā)送連接請(qǐng)求,而InetSocketAddress對(duì)象以要連接的服務(wù)器IP地址和要連接的服務(wù)器端口號(hào)作為構(gòu)造方法參數(shù)。ServerSocket對(duì)象生成后負(fù)責(zé)監(jiān)聽(tīng)來(lái)自客戶的TCP連接請(qǐng)求,使用accept方法來(lái)監(jiān)聽(tīng)和通過(guò)客戶端進(jìn)程的連接請(qǐng)求,并返回一個(gè)Socket類(lèi)型的對(duì)象。服務(wù)器端Socket對(duì)象創(chuàng)建成功后,客戶端與服務(wù)器就建立了一個(gè)TCP連接,并可以通過(guò)這個(gè)連接在兩個(gè)套接字之間進(jìn)行通信。Socket類(lèi)還提供了返回輸出流、輸入流的方法,用于發(fā)送、接受數(shù)據(jù)。如果希望設(shè)置客戶端Socket請(qǐng)求與服務(wù)器建立連接的等待時(shí)間,則可調(diào)用Socket的connect方法設(shè)置超時(shí)時(shí)間,當(dāng)連接請(qǐng)求超時(shí)時(shí),便會(huì)拋出連接超時(shí)異常。另外,ServerSocket的構(gòu)造方法還提供設(shè)定接收客戶端請(qǐng)求的隊(duì)列長(zhǎng)度的功能,當(dāng)請(qǐng)求數(shù)量大于隊(duì)列設(shè)定長(zhǎng)度時(shí),新的連接請(qǐng)求再傳入服務(wù)器無(wú)法進(jìn)入等待隊(duì)列,客戶端便會(huì)返回異常。僅當(dāng)ServerSocket調(diào)用accept方法從連接隊(duì)列中取出任務(wù),新的連接請(qǐng)求才允許進(jìn)入等待隊(duì)列。但是該隊(duì)列為等待隊(duì)列,并不能實(shí)現(xiàn)多線程與服務(wù)器并發(fā)交互,在實(shí)際中應(yīng)用方面并不廣泛。

2.2 服務(wù)器的多線程實(shí)現(xiàn)

當(dāng)服務(wù)器接收到第一個(gè)客戶請(qǐng)求時(shí),連接建立開(kāi)始通信,其他客戶請(qǐng)求連接時(shí),這些連接請(qǐng)求,必須進(jìn)入等待隊(duì)列等待服務(wù)器響應(yīng),直到上一個(gè)客戶的任務(wù)完成并結(jié)束,導(dǎo)致服務(wù)器無(wú)法支持多用戶并發(fā)訪問(wèn)并與多個(gè)客戶同時(shí)交互。為了實(shí)現(xiàn)服務(wù)器能同時(shí)與多個(gè)客戶通信并且能夠及時(shí)給出響應(yīng),可以設(shè)計(jì)服務(wù)器主線程負(fù)責(zé)監(jiān)聽(tīng)和接收客戶連接請(qǐng)求并與客戶建立連接,然后為每個(gè)連接客戶創(chuàng)建一個(gè)工作線程,這些工作線程接收主線程提供的剛由accept方法創(chuàng)建的服務(wù)器端socket作為參數(shù),并由這些線程完成對(duì)應(yīng)客戶發(fā)送的任務(wù)。由于無(wú)限制分配線程的創(chuàng)建銷(xiāo)毀開(kāi)銷(xiāo)很大而且容易造成系統(tǒng)內(nèi)存不足,這些工作線程可以被預(yù)先創(chuàng)建完成并保存在線程池中,在線程池中,提前保存了一定數(shù)量這樣的線程,它們?cè)诳臻e狀態(tài)不斷詢問(wèn)任務(wù)隊(duì)列是否有新的等待任務(wù),取出任務(wù)隊(duì)列中的任務(wù)并執(zhí)行,當(dāng)一個(gè)線程執(zhí)行完對(duì)應(yīng)的任務(wù)時(shí),就會(huì)繼續(xù)詢問(wèn)任務(wù)隊(duì)列是否有新的等待任務(wù)并讀取任務(wù)隊(duì)列中的下一個(gè)任務(wù)。線程池實(shí)現(xiàn)了將工作線程回收利用,使每個(gè)線程池中的線程能夠重新完成新的任務(wù),使程序員可以根據(jù)系統(tǒng)的CPU性能、內(nèi)存大小等系統(tǒng)屬性確定線程池中線程的數(shù)目。但是線程池的問(wèn)題在于如果客戶端通信異常終止,會(huì)導(dǎo)致線程資源的泄露,如果多次發(fā)生會(huì)使得最終線程池中無(wú)線程可用,服務(wù)器雖與客戶建立連接但由于線程池中線程不可用無(wú)法響應(yīng)客戶請(qǐng)求,還有多線程程序最容易產(chǎn)生的并發(fā)和死鎖問(wèn)題等風(fēng)險(xiǎn)。例如,線程A需要同步等待線程B的執(zhí)行結(jié)果,那么如果不能獲得B的結(jié)果,A將可能死鎖,因此應(yīng)避免將相關(guān)線程加入工作隊(duì)列,保證執(zhí)行的線程任務(wù)盡量單一;假設(shè)工作線程執(zhí)行過(guò)程中被阻塞(如由于各種原因,數(shù)據(jù)傳輸?shù)慕K止標(biāo)識(shí)丟失,導(dǎo)致客戶端一直在讀取數(shù)據(jù)階段,無(wú)法繼續(xù)輸入指令),致使該線程持續(xù)處于阻塞狀態(tài)。如果線程池中的所有線程都由于各種原因處于阻塞狀態(tài),線程池就無(wú)法繼續(xù)處理新任務(wù),服務(wù)器也將因此癱瘓,對(duì)此可以通過(guò)調(diào)用ServerSocket所提供的setSoTimeout方法,設(shè)置等待客戶響應(yīng)的連接超時(shí)時(shí)間,如果連接超時(shí),工作線程將主動(dòng)結(jié)束與客戶的連接;對(duì)于線程異常終止導(dǎo)致線程泄露,可以使用FixedThreadPool,如果在線程正常關(guān)閉前由于異常原因致使線程異常終止,會(huì)創(chuàng)建一個(gè)新線程代替原線程完成接下來(lái)的任務(wù)。

2.3 服務(wù)器與客戶之間的UDP傳輸

在Java中,UDP的特定socket的類(lèi)為DatagramSocket負(fù)責(zé)接收和發(fā)送UDP數(shù)據(jù)報(bào),其提供的receive和send方法讓服務(wù)器和客戶可以接收、發(fā)送數(shù)據(jù);通過(guò)創(chuàng)建DatagramPacket對(duì)象表示UDP數(shù)據(jù)單元數(shù)據(jù)包。需要注意的是,DatagramPacket指定了數(shù)據(jù)內(nèi)容和要發(fā)送的字節(jié)數(shù);作為接收數(shù)據(jù)的DatagramPacket無(wú)需指定發(fā)送方地址;發(fā)送數(shù)據(jù)的DatagramPacket則必須設(shè)定數(shù)據(jù)到達(dá)的目的IP地址和端口。對(duì)于傳輸非文本文件,應(yīng)采用字節(jié)流以避免讀取格式的錯(cuò)誤,并且所有文件的儲(chǔ)存是都是字節(jié)的儲(chǔ)存,所以采用字節(jié)流傳輸。

服務(wù)器UDP發(fā)送服務(wù)(實(shí)現(xiàn)get方法)Get:

3 系統(tǒng)實(shí)現(xiàn)

該系統(tǒng)類(lèi)似ftp網(wǎng)絡(luò)文件服務(wù)程序,由于Java為socket的編程提供了豐富發(fā)工具,該系統(tǒng)以Java Socket TCP和UDP為基礎(chǔ)實(shí)現(xiàn),包含服務(wù)器端和客戶端;該系統(tǒng)使用TCP協(xié)議傳輸用戶指令和服務(wù)器反饋,使用UDP協(xié)議傳輸文件;服務(wù)器端支持多用戶并發(fā)訪問(wèn)。當(dāng)控制臺(tái)顯示連接時(shí),客戶可在控制臺(tái)輸入以下指令獲得服務(wù)器的對(duì)應(yīng)反饋:

通過(guò)TCP連接時(shí),服務(wù)器端需保存用戶當(dāng)前所在目錄的信息(初始連接時(shí)為服務(wù)器指定的根目錄),通過(guò)cd ..可退到上一級(jí)目錄,且當(dāng)前目錄為根目錄時(shí),不做變動(dòng)。TCP連接時(shí),客戶端可能一次接收多行數(shù)據(jù),需循環(huán)從輸入流中讀取,服務(wù)器端可在每次輸出結(jié)束時(shí)多輸出一個(gè)空行,客戶端根據(jù)空行來(lái)判斷每次輸入的結(jié)束。get命令的執(zhí)行:可先發(fā)送給TCP連接,判斷get后的參數(shù)在當(dāng)前目錄下是否為普通文件,若不是,回復(fù)提示信息,若是,回復(fù)客戶端特定信息(如OK),以及該文件的物理路徑和大小,客戶端接收到OK后,緊接著讀取后續(xù)的信息,再通過(guò)UDP請(qǐng)求該文件。UDP傳輸文件時(shí),需將文件分次讀取到byte[]緩存中,每次封裝一個(gè)DatagramPacket,依次發(fā)送給客戶端,為了確保發(fā)送的順序,可在每次發(fā)送結(jié)束時(shí)通過(guò)TimeUnit.MICROSECONDS.sleep(1)來(lái)限制發(fā)送的速度;客戶端接收時(shí),循環(huán)接收DatagramPacket,循環(huán)次數(shù)為文件大小/緩存大小+1。

對(duì)于客戶端,不論是TCP協(xié)議的socket還是UDP協(xié)議的socket,代碼的結(jié)束部分都會(huì)調(diào)用socket.close()方法將客戶端對(duì)應(yīng)的socket關(guān)閉,以避免socket超時(shí)關(guān)閉。而Handler類(lèi)作為一個(gè)工作線程類(lèi),調(diào)用了LS、Cd、Get類(lèi)來(lái)完成ls、cd和get功能。由于代碼在同一臺(tái)計(jì)算機(jī)測(cè)試,所選IP地址固定為127.0.0.1(可更改)。傳輸文件的保存路徑保存在EchoClient中,可手動(dòng)更改。這是一個(gè)簡(jiǎn)易的網(wǎng)絡(luò)文件查找傳輸系統(tǒng),其通過(guò)Java實(shí)現(xiàn),可以幫助了解計(jì)算機(jī)網(wǎng)絡(luò)、分布式計(jì)算、socket編程以及Java編程的相關(guān)知識(shí)。

4 結(jié)束語(yǔ)

計(jì)算機(jī)網(wǎng)絡(luò)近六十年的發(fā)展將人類(lèi)的生活徹底改變,它將不同空間不同時(shí)間的計(jì)算機(jī)聯(lián)系起來(lái),對(duì)人與人之間的聯(lián)系交流、科學(xué)技術(shù)的研究發(fā)展產(chǎn)生了巨大變革。分布式計(jì)算將多個(gè)計(jì)算機(jī)相互連接作為一個(gè)整體,在相同或不同的軟硬件環(huán)境下執(zhí)行相同或不同的任務(wù),其在分散的計(jì)算機(jī)之間建立緊密的連接,充分的利用計(jì)算機(jī)資源,提升效率,降低成本,引起的技術(shù)變革和更新也將促進(jìn)人類(lèi)科學(xué)技術(shù)的發(fā)展。

猜你喜歡
空閑服務(wù)器端線程
恩賜
Linux環(huán)境下基于Socket的數(shù)據(jù)傳輸軟件設(shè)計(jì)
“鳥(niǎo)”字謎
淺析異步通信層的架構(gòu)在ASP.NET 程序中的應(yīng)用
彪悍的“寵”生,不需要解釋
淺談linux多線程協(xié)作
基于Qt的安全即時(shí)通訊軟件服務(wù)器端設(shè)計(jì)
基于上下文定界的Fork/Join并行性的并發(fā)程序可達(dá)性分析*
Linux線程實(shí)現(xiàn)技術(shù)研究
網(wǎng)頁(yè)防篡改中分布式文件同步復(fù)制系統(tǒng)
乾安县| 上杭县| 内江市| 都江堰市| 南安市| 视频| 龙川县| 普洱| 孝感市| 宁武县| 武冈市| 白水县| 舟曲县| 喀喇沁旗| 绥化市| 正镶白旗| 平南县| 仁寿县| 习水县| 韶关市| 长汀县| 柳河县| 青龙| 晋江市| 鄂托克前旗| 阜宁县| 图片| 思茅市| 宣城市| 永平县| 温州市| 景宁| 平度市| 景泰县| 会同县| 石景山区| 永福县| 宁陕县| 福贡县| 万盛区| 远安县|