?

基于JavaSocket編程的網絡文件服務系統研究

2022-07-08 07:19李柯
電子技術與軟件工程 2022年2期
關鍵詞:空閑服務器端線程

李柯

(西北工業大學 陜西省西安市 710000)

1 基本介紹

實際上進程之間的通信是通過向雙方的套接字發送報文(應用程序交換信息分組)來實現的,進程所在的應用層通過套接字與運輸層連接。根據使用的運輸層協議不同,還可分為UDP套接字和TCP套接字。套接字充當一個“運輸和預處理者”,檢查運輸層協議發來的報文并采取適當的動作。

集中式系統的部件(計算機)局限在一個地方,使用限制很多,難以實現系統的拓展、設備的移動,缺乏靈活性和便捷性,且難以應用在包括Web文檔系統、學習工作中的工作流系統等當中。而對于分布式系統,系統的部件(計算機)不在同一地理位置,在物理上相互獨立,地位平等,但卻存在緊密的合作,用戶獲取資源時不需要知道資源在系統中的具體位置,分布式系統在用戶面前將呈現出一個單一的系統整體。其開發、可擴展、異構、透明、安全的特點,使分布式計算系統被用于許多不同類型的應用中,如共享存儲器多處理機。

2 基于TCP建立連接通訊、UDP傳輸數據的文件服務系統

于是我們是否能利用高級語言所提供的一些方法和代碼庫,通過代碼的組織管理,實現利用TCP和UDP進行多線程傳輸數據的系統。由于Java編程語言面向對象、可移植性強(Java在自己的虛擬機JVM上編譯運行,JVM上具有完整的虛擬硬件系統和完整的指令系統,使得Java程序在其他平臺上只要擁有JVM就能不加修改地運行)、功能強大、操作簡單,而且Java提供了多線程實現的類與接口,使利用Java實現多線程系統變得相對更加簡單。

想要實現在網絡中進程之間通信,就要對每一個進程賦予唯一標識。網絡中的進程需要利用網絡層的IP地址唯一標識網絡中的主機,傳輸層的所用協議和端口唯一標識主機中的進程。所以,形成了三元組(IP地址,協議,端口)來標識網絡的進程。進程在網絡中的通信通過該三元組唯一標識其它進程并與之進行交互。

2.1 建立服務器與客戶之間的TCP連接

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

2.2 服務器的多線程實現

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

2.3 服務器與客戶之間的UDP傳輸

在Java中,UDP的特定socket的類為DatagramSocket負責接收和發送UDP數據報,其提供的receive和send方法讓服務器和客戶可以接收、發送數據;通過創建DatagramPacket對象表示UDP數據單元數據包。需要注意的是,DatagramPacket指定了數據內容和要發送的字節數;作為接收數據的DatagramPacket無需指定發送方地址;發送數據的DatagramPacket則必須設定數據到達的目的IP地址和端口。對于傳輸非文本文件,應采用字節流以避免讀取格式的錯誤,并且所有文件的儲存是都是字節的儲存,所以采用字節流傳輸。

服務器UDP發送服務(實現get方法)Get:

3 系統實現

該系統類似ftp網絡文件服務程序,由于Java為socket的編程提供了豐富發工具,該系統以Java Socket TCP和UDP為基礎實現,包含服務器端和客戶端;該系統使用TCP協議傳輸用戶指令和服務器反饋,使用UDP協議傳輸文件;服務器端支持多用戶并發訪問。當控制臺顯示連接時,客戶可在控制臺輸入以下指令獲得服務器的對應反饋:

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

對于客戶端,不論是TCP協議的socket還是UDP協議的socket,代碼的結束部分都會調用socket.close()方法將客戶端對應的socket關閉,以避免socket超時關閉。而Handler類作為一個工作線程類,調用了LS、Cd、Get類來完成ls、cd和get功能。由于代碼在同一臺計算機測試,所選IP地址固定為127.0.0.1(可更改)。傳輸文件的保存路徑保存在EchoClient中,可手動更改。這是一個簡易的網絡文件查找傳輸系統,其通過Java實現,可以幫助了解計算機網絡、分布式計算、socket編程以及Java編程的相關知識。

4 結束語

計算機網絡近六十年的發展將人類的生活徹底改變,它將不同空間不同時間的計算機聯系起來,對人與人之間的聯系交流、科學技術的研究發展產生了巨大變革。分布式計算將多個計算機相互連接作為一個整體,在相同或不同的軟硬件環境下執行相同或不同的任務,其在分散的計算機之間建立緊密的連接,充分的利用計算機資源,提升效率,降低成本,引起的技術變革和更新也將促進人類科學技術的發展。

猜你喜歡
空閑服務器端線程
恩賜
Linux環境下基于Socket的數據傳輸軟件設計
“鳥”字謎
淺析異步通信層的架構在ASP.NET 程序中的應用
彪悍的“寵”生,不需要解釋
淺談linux多線程協作
基于Qt的安全即時通訊軟件服務器端設計
基于上下文定界的Fork/Join并行性的并發程序可達性分析*
Linux線程實現技術研究
網頁防篡改中分布式文件同步復制系統
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合