C++基于局域網(wǎng)Linux環(huán)境下的心跳檢測系統(tǒng)實現(xiàn).doc_第1頁
C++基于局域網(wǎng)Linux環(huán)境下的心跳檢測系統(tǒng)實現(xiàn).doc_第2頁
C++基于局域網(wǎng)Linux環(huán)境下的心跳檢測系統(tǒng)實現(xiàn).doc_第3頁
C++基于局域網(wǎng)Linux環(huán)境下的心跳檢測系統(tǒng)實現(xiàn).doc_第4頁
C++基于局域網(wǎng)Linux環(huán)境下的心跳檢測系統(tǒng)實現(xiàn).doc_第5頁
已閱讀5頁,還剩55頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

編 號: 審定成績: 重慶郵電大學(xué)畢業(yè)設(shè)計(論文)設(shè)計(論文)題目:c+基于局域網(wǎng)linux環(huán)境下的心跳檢測系統(tǒng)實現(xiàn)學(xué) 院 名 稱 :計算機科學(xué)與技術(shù)學(xué)院學(xué) 生 姓 名 :胡 凱專 業(yè) :計算機科學(xué)與技術(shù)專業(yè)班 級 :0490601學(xué) 號 :06100107指 導(dǎo) 教 師 :易 芝答辯組 負(fù)責(zé)人 :填表時間: 2010 年 6 月重慶郵電大學(xué)教務(wù)處-58-摘 要當(dāng)今世界的網(wǎng)絡(luò)飛速發(fā)展,但也因此也產(chǎn)生了許多網(wǎng)絡(luò)故障,心跳檢測技術(shù)作為一種故障檢測技術(shù),在當(dāng)今服務(wù)器市場有很大需求。心跳檢測技術(shù)是一種檢測網(wǎng)絡(luò)連接故障的技術(shù),它通過在服務(wù)器端和客戶端裝上各自的心跳檢測軟件,就可以根據(jù)發(fā)送的心跳報文來監(jiān)測故障,判斷各個網(wǎng)絡(luò)節(jié)點的連接是否正常1。 本文研究了心跳檢測技術(shù)在linux平臺下的實現(xiàn),設(shè)計了一款能在局域網(wǎng)上運行的心跳檢測系統(tǒng)。該系統(tǒng)采用tcp/udp協(xié)議,以c/s模式進(jìn)行開發(fā)。服務(wù)器充當(dāng)主控節(jié)點,客戶端充當(dāng)外圍節(jié)點,通過客戶端發(fā)送心跳報文的方法來實現(xiàn)心跳檢測。系統(tǒng)在節(jié)點的局域網(wǎng)中使用,能達(dá)到很高的成功率?!娟P(guān)鍵詞】心跳檢測 主控節(jié)點 外圍節(jié)點 報文 linuxabstractnetwork technology of todays world has the rapid development ,but also produces so many network failure, heartbeat detection technology is a detection technology as a network failure detection , and has much demand in todays server market.heartbeat detection technology is a network connection failure detection technology, server and client need only install on each heartbeat detection software, you can send packets to monitor heart failure, determine whether the various network nodes is in the normal .in this paper, the heartbeat detection technology implementation in the linux platform, designed a run in lan heartbeat detection system. the system uses tcp / udp protocol, to c / s model for development. server acts as the master node, the client acts as the external nodes, through the heartbeat messages sent by the client to achieve the heartbeat detection methods. system used in local area network node can achieve a high success rate.【key words】heartbeat detection master node peripheral node message linux目 錄abstract2前 言4第一章 系統(tǒng)簡介6第一節(jié) 心跳檢測機制6第二節(jié) 本文設(shè)計的心跳檢測系統(tǒng)6第三節(jié) 本章小結(jié)7第二章開發(fā)環(huán)境、工具和技術(shù)8第一節(jié)linux的介紹8第二節(jié)gcc簡介9一、什么是gcc9二、gcc的基本規(guī)則10三、gcc的基本用法10四、執(zhí)行過程11第三節(jié) linux下的網(wǎng)絡(luò)編程技術(shù)11一、socket編程介紹11二、tcp/udp開發(fā)簡介16第四節(jié) 本章小結(jié)17第三章 系統(tǒng)的分析與設(shè)計18第一節(jié) 需求分析18一、問題定義18二、可行性研究18三、用戶需求18四、系統(tǒng)整體用例圖19第二節(jié) 概要設(shè)計19一、設(shè)計指導(dǎo)思想20二、心跳檢測系統(tǒng)的整體結(jié)構(gòu)圖20三、總體設(shè)計21第三節(jié)詳細(xì)設(shè)計22一、心跳表注冊表的設(shè)計22二、報文格式的設(shè)計24三、外圍節(jié)點的設(shè)計26四、主控節(jié)點的設(shè)計27第四節(jié) 本章小結(jié)31第四章 心跳檢測系統(tǒng)的實現(xiàn)32第一節(jié) linux下開發(fā)環(huán)境32一、編譯環(huán)境32二、運行環(huán)境33第二節(jié) 程序的實現(xiàn)35一、外圍節(jié)點的實現(xiàn)35二、主控節(jié)點的設(shè)計37第三節(jié) 本章小節(jié)40第五章 系統(tǒng)測試41第一節(jié) 測試環(huán)境41第二節(jié) 測試方法41一、黑盒測試42二、測試步驟42第三節(jié) 本章小結(jié)48結(jié) 論49參考文獻(xiàn)51附 錄52一、英文原文52二、中文翻譯56前 言網(wǎng)絡(luò)是一個龐大復(fù)雜的系統(tǒng),有成千上萬臺設(shè)備節(jié)點,經(jīng)常會出現(xiàn)連接故障,我們不可能用人力去監(jiān)測,這時負(fù)責(zé)監(jiān)測網(wǎng)絡(luò)故障的心跳檢測軟件由此產(chǎn)生。心跳檢測系統(tǒng)是基于c/s架構(gòu)開發(fā)的網(wǎng)絡(luò)檢測系統(tǒng),隨著網(wǎng)絡(luò)技術(shù)的發(fā)展而發(fā)展,在當(dāng)今服務(wù)器市場上有很大需求,也日趨成熟化。比如linux平臺下的heartbeat集群軟件包就是成功的典型。我相信,在當(dāng)今it技術(shù)的推動下,心跳檢測在未來幾年會有更廣闊的發(fā)展空間。在了解了心跳檢測的基本原理和linux網(wǎng)絡(luò)編程的基本方法之后,我設(shè)計了一個可以在局域網(wǎng)上進(jìn)行網(wǎng)絡(luò)連接檢測的心跳檢測系統(tǒng)。并對里面涉及的技術(shù)原理,設(shè)計思想進(jìn)行了相關(guān)討論。第一章 系統(tǒng)簡介第一節(jié) 心跳檢測機制在分布式系統(tǒng)中,有成千上萬個設(shè)備節(jié)點通過有線或者無線網(wǎng)絡(luò)連接。這些節(jié)點和網(wǎng)絡(luò)隨時可能發(fā)生故障,從而導(dǎo)致部分節(jié)點或者網(wǎng)絡(luò)癱瘓。為了確保整個系統(tǒng)正常工作,主控節(jié)點應(yīng)該能隨時知道其他節(jié)點當(dāng)前是否在正常工作。如果用人力去監(jiān)控,則會造成很大的開銷,且節(jié)點是否癱瘓有時無法從外表判斷。心跳檢測系統(tǒng)可以節(jié)省人力,根據(jù)外圍節(jié)點定期發(fā)送的報文來判斷設(shè)備和網(wǎng)絡(luò)是否發(fā)生故障。心跳檢測技術(shù)是分布式嵌入式系統(tǒng)中一種常見的故障檢測方法。在心跳檢測中,外圍節(jié)點將周期性向主控節(jié)點發(fā)送心跳報文。如果過一段時間之后,主控節(jié)點沒有收到外圍節(jié)點的心跳報文,則認(rèn)為此節(jié)點或相關(guān)網(wǎng)絡(luò)出現(xiàn)故障,并向管理員報告。它有如下特點:基于c/s模式,主控節(jié)點(服務(wù)器端)判斷外圍節(jié)點(客戶端)是否正常運行,一般采用定時發(fā)送簡單的心跳報文,如果在指定時間段內(nèi)未收到對方響應(yīng),則判斷連接出現(xiàn)故障。用于檢測網(wǎng)絡(luò)的異常斷開。發(fā)包方可以是客戶端也可以是服務(wù)器端,看哪邊實現(xiàn)方便合理。一般是客戶端,服務(wù)器也可以定時輪詢發(fā)心跳下去(我的系統(tǒng)是采用客戶端發(fā)報文)。檢測方法就是外圍節(jié)點每隔幾分鐘發(fā)送一個心跳報文給主控節(jié)點,服務(wù)端收到后回復(fù)一個響應(yīng)報文。如果服務(wù)端在規(guī)定時間內(nèi)沒有收到客戶端信息則視連接斷開。第二節(jié) 本文設(shè)計的心跳檢測系統(tǒng)在介紹了心跳檢測系統(tǒng)的概念、特點、作用之后,下面介紹了我所設(shè)計的系統(tǒng)的一些情況。由于該設(shè)計主要是針對10臺左右的小范圍的局域網(wǎng)設(shè)計的心跳檢測系統(tǒng),沒有涉及到數(shù)據(jù)庫存儲的相關(guān)知識,因此該系統(tǒng)的優(yōu)點是所需要的硬件代價小,實現(xiàn)起來的網(wǎng)絡(luò)連接相對簡單,能針對自己組建的局域網(wǎng)來測試。當(dāng)然,該設(shè)計的功能差了很多,比如在數(shù)據(jù)庫中記錄節(jié)點出錯時間,監(jiān)控節(jié)點數(shù)量的多少,網(wǎng)絡(luò)阻塞引起的延時等方面并沒有涉及到。我相信,我今后在學(xué)習(xí)更多網(wǎng)絡(luò)故障檢測技術(shù)和網(wǎng)絡(luò)編程技術(shù)后,會將上述功能一一實現(xiàn)。 我的設(shè)計在linux平臺下,采用了c/s模式,服務(wù)器端充當(dāng)主控節(jié)點,客戶端充當(dāng)外圍節(jié)點,外圍節(jié)點先發(fā)送tcp報文進(jìn)行和主控節(jié)點建立連接,在建立連接成功后,發(fā)送心跳報文,心跳報文則采用udp格式設(shè)計。而后每隔一秒發(fā)送一次心跳報文,主控節(jié)點根據(jù)心跳報文來檢測網(wǎng)絡(luò)連接是否正常。第三節(jié) 本章小結(jié)本章先從心跳檢測的用途出發(fā),介紹了心跳檢測的概念,以及它使用的原理,使大家對心跳檢測有了大致的了解。最后大致介紹了我自己設(shè)計的心跳檢測系統(tǒng)的一些情況,包括優(yōu)缺點和大致的實現(xiàn)情況。第二章 開發(fā)環(huán)境、工具和技術(shù)第一節(jié) linux的介紹linux是一類unix計算機操作系統(tǒng)的統(tǒng)稱。linux操作系統(tǒng)的內(nèi)核的名字也是“l(fā)inux”。linux操作系統(tǒng)也是自由軟件和開放源代碼發(fā)展中最著名的例子。嚴(yán)格來講,linux這個詞本身只表示linux內(nèi)核,但在實際上人們已經(jīng)習(xí)慣了用linux來形容整個基于linux內(nèi)核,并且使用gnu 工程各種工具和數(shù)據(jù)庫的操作系統(tǒng)。linux得名于計算機業(yè)余愛好者linus torvalds。當(dāng)時他是芬蘭赫爾辛基大學(xué)的學(xué)生。他的目的是想設(shè)計一個代替minix(是由一位名叫andrew tannebaum的計算機教授編寫的一個操作系統(tǒng)示教程序)的操作系統(tǒng),這個操作系統(tǒng)可用于386、486或奔騰處理器的個人計算機上,并且具有unix操作系統(tǒng)的全部功能,因而開始了linux雛形的設(shè)計。出于愛好,他根據(jù)可在低檔機上使用的minix設(shè)計了一個系統(tǒng)核心linux 0.01,但沒有使用任何minix或unix的源代碼。他通過usenet(就是新聞組)宣布這是一個免費的系統(tǒng),主要在x86電腦上使用,希望大家一起來將它完善,并將源代碼放到了芬蘭的ftp站點上任人免費下載。linux以它的靈活性和高效性著稱。能夠在個人計算機上面實現(xiàn)全部的unix的特性。具有多任務(wù)、多用戶的能力。linux在gnu的gpl公共許可權(quán)下免費獲得。linux不僅僅包括完整的操作系統(tǒng),還包括文本編輯器、高級語言編譯器等應(yīng)用軟件。它還包括帶有多個窗口管理器的x-windows圖形用戶界面。目前,linux能夠運用于各種版本的cpu的計算機上,還能運用于一些手持設(shè)備,比如說,pda,游戲機,手機,嵌入式產(chǎn)品等等。由于linux的開源性以及免費性,很多廠家都選擇應(yīng)用linux開發(fā),以降低成本,在增強競爭力的同時也推進(jìn)了linux系統(tǒng)的發(fā)展。 絕大多數(shù)基于linux內(nèi)核的操作系統(tǒng)使用了大量的gnu軟件,包括了shell程序、工具、程序庫、編譯器及工具,還有許多其他程序,例如emacs。linux的基本思想有兩點:第一,一切都是文件;第二,每個軟件都有確定的用途。其中第一條詳細(xì)來講就是系統(tǒng)中的所有都?xì)w結(jié)為一個文件,包括命令、硬件和軟件設(shè)備、操作系統(tǒng)、進(jìn)程等等對于操作系統(tǒng)內(nèi)核而言,都被視為擁有各自特性或類型的文件。至于說linux是基于unix的,很大程度上也是因為這兩者的基本思想十分相近。linux的優(yōu)點集中體現(xiàn)在以下幾點:低廉性:基于其低廉成本與高度可設(shè)定性,linux常常被應(yīng)用于嵌入式系統(tǒng),例如機頂盒、移動電話及行動裝置等。在移動電話上,linux已經(jīng)成為與symbian os、windows mobile系統(tǒng)并列的三大智能手機操作系統(tǒng)之一;而在移動裝置上,則成為windows ce與palm os外之另一個選擇。廣泛性:基于linux的開源性給人們帶來的巨大誘惑,linux的的應(yīng)用越來越廣,linux社區(qū)的人員的增多,致使基于linux的開發(fā)越來越方便容易。根據(jù)2005年11月號的top500超級電腦列表,顯示世上最快速的兩組超級電腦都是使用linux作為其操作系統(tǒng)。而在表列的500套系統(tǒng)里,采用linux為操作系統(tǒng)的,占了371組(即74.2%),其中的前十位者,有7組是使用linux的。目前,除了一部分專家之外,大多數(shù)人都不自己選擇每一樣組件或自行設(shè)置,而是直接使用linux套件。靈活性:linux以它的高效性和靈活性著稱。它能夠在pc計算機上實現(xiàn)全部的unix特性,具有多任務(wù)、多用戶的能力。linux是在gnu公共許可權(quán)限下免費獲得的,是一個符合posix標(biāo)準(zhǔn)的操作系統(tǒng)。linux操作系統(tǒng)軟件包不僅包括完整的linux操作系統(tǒng),而且還包括了文本編輯器、高級語言編譯器等應(yīng)用軟件。它還包括帶有多個窗口管理器的x-window圖形用戶界面,如同我們使用windows nt一樣,允許我們使用窗口、圖標(biāo)和菜單對系統(tǒng)進(jìn)行操作。總的來說,linux由于有著諸多windows操作系統(tǒng)所缺乏的優(yōu)點,能夠讓我們在嵌入式應(yīng)用中如魚得水2。第二節(jié) gcc簡介一、 什么是gccgcc是gnu公社的一個項目。是一個用于編程開發(fā)的自由編譯器。最初,gcc只是一個c語言編譯器,它是gnu c compiler 的英文縮寫。隨著眾多自由開發(fā)者的加入和gcc自身的發(fā)展,如今的gcc已經(jīng)是一個包含眾多語言的編譯器了。其中包括 c,c+,ada,object c和java等。所以,gcc也由原來的gnu c compiler變?yōu)間nu compiler collection。也就是 gnu編譯器家族的意思。當(dāng)然,如今的gcc借助于它的特性,可以交叉編譯,即在一個平臺下編譯另一個平臺的代碼。直到現(xiàn)在,gcc的歷史仍然在繼續(xù),它的傳奇仍然被人所傳頌。而且更重要的是gcc完全是一款免費的自由軟件,加之其強大的功能所以深受廣大用戶的喜愛。二、gcc的基本規(guī)則gcc所遵循的部分約定規(guī)則: .c為后綴的文件,c語言源代碼文件; .a為后綴的文件,是由目標(biāo)文件構(gòu)成的檔案庫文件; .c,.cc或.cxx 為后綴的文件,是c+源代碼文件; .h為后綴的文件,是程序所包含的頭文件; .i 為后綴的文件,是已經(jīng)預(yù)處理過的c源代碼文件; .ii為后綴的文件,是已經(jīng)預(yù)處理過的c+源代碼文件; .m為后綴的文件,是objective-c源代碼文件; .o為后綴的文件,是編譯后的目標(biāo)文件; .s為后綴的文件,是匯編語言源代碼文件; .s為后綴的文件,是經(jīng)過預(yù)編譯的匯編語言源代碼文件。三、gcc的基本用法在使用gcc編譯器的時候,我們必須給出一系列必要的調(diào)用參數(shù)和文件名稱。gcc編譯器的調(diào)用參數(shù)大約有100多個,其中多數(shù)參數(shù)我們可能根本就用不到,這里只介紹其中最基本、最常用的參數(shù)。 gcc最基本的用法是gcc options filenames 其中options就是編譯器所需要的參數(shù),filenames給出相關(guān)的文件名稱。 -c,只編譯,不連接成為可執(zhí)行文件,編譯器只是由輸入的.c等源代碼文件生成.o為后綴的目標(biāo)文件,通常用于編譯不包含主程序的子程序文件。 -o output_filename,確定輸出文件的名稱為output_filename,同時這個名稱不能和源文件同名。如果不給出這個選項,gcc就給出預(yù)設(shè)的可執(zhí)行文件a.out。 -g,產(chǎn)生符號調(diào)試工具(gnu的gdb)所必要的符號資訊,要想對源代碼進(jìn)行調(diào)試,我們就必須加入這個選項。 -o,對程序進(jìn)行優(yōu)化編譯、連接,采用這個選項,整個源代碼會在編譯、連接過程中進(jìn)行優(yōu)化處理,這樣產(chǎn)生的可執(zhí)行文件的執(zhí)行效率可以提高,但是,編譯、連接的速度就相應(yīng)地要慢一些。 -o2,比-o更好的優(yōu)化編譯、連接,當(dāng)然整個編譯、連接過程會更慢。 -idirname,將dirname所指出的目錄加入到程序頭文件目錄列表中,是在預(yù)編譯過程中使用的參數(shù)。c程序中的頭文件包含兩種情況 a)#include b)#include “myinc.h” 其中,a類使用尖括號(),b類使用雙引號(“ ”)。對于a類,預(yù)處理程序cpp在系統(tǒng)預(yù)設(shè)包含文件目錄(如/usr/include)中搜尋相應(yīng)的文件,而b類,預(yù)處理程序在目標(biāo)文件的文件夾內(nèi)搜索相應(yīng)文件。四、執(zhí)行過程 雖然我們稱gcc是c語言的編譯器,但使用gcc由c語言源代碼文件生成可執(zhí)行文件的過程不僅僅是編譯的過程,而是要經(jīng)歷四個相互關(guān)聯(lián)的步驟:預(yù)編譯,編譯,匯編和鏈接 命令gcc首先調(diào)用cpp進(jìn)行預(yù)處理,在預(yù)處理過程中,對源代碼文件中的文件包含(include)、預(yù)編譯語句(如宏定義define等)進(jìn)行分析。接著調(diào)用cc1進(jìn)行編譯,這個階段根據(jù)輸入文件生成以.o為后綴的目標(biāo)文件。匯編過程是針對匯編語言的步驟,調(diào)用as進(jìn)行工作,一般來講,.s為后綴的匯編語言源代碼文件和匯編、.s為后綴的匯編語言文件經(jīng)過預(yù)編譯和匯編之后都生成以.o為后綴的目標(biāo)文件。當(dāng)所有的目標(biāo)文件都生成之后,gcc就調(diào)用ld來完成最后的關(guān)鍵性工作,這個階段就是連接。在連接階段,所有的目標(biāo)文件被安排在可執(zhí)行程序中的恰當(dāng)?shù)奈恢?,同時,該程序所調(diào)用到的庫函數(shù)也從各自所在的檔案庫中連到合適的地方3。第三節(jié) linux下的網(wǎng)絡(luò)編程技術(shù)一、socket編程介紹在介紹心跳檢測的詳細(xì)設(shè)計之前,首先介紹linux下的網(wǎng)絡(luò)程序設(shè)計方法。在linux系統(tǒng)中,最常用的網(wǎng)絡(luò)應(yīng)用編程結(jié)構(gòu)是unix bsd的套接字接口。socket編程有字節(jié)流和數(shù)據(jù)報兩種主要類型,分別對應(yīng)tcp協(xié)議和udp協(xié)議。其中字節(jié)流socket定義了一種可靠的面向連接的服務(wù),實現(xiàn)了無差錯無重復(fù)的順序數(shù)據(jù)傳輸。數(shù)據(jù)報socket定義了一種無連接的服務(wù),數(shù)據(jù)通過相互獨立的報文進(jìn)行傳輸,是無序的,并且無法保證可靠無差錯。無連接服務(wù)器一般都是面向事務(wù)處理的,一個請求一個應(yīng)答就完成了客戶和服務(wù)器之間的交互。下面就是本系統(tǒng)所用到的socket編程函數(shù): 創(chuàng)建套接字:int socket( int domain, int type, int protocol ); 應(yīng)用程序調(diào)用socket函數(shù)來創(chuàng)建一個能夠進(jìn)行網(wǎng)絡(luò)通信的套接字。domain:指定應(yīng)用程序使用的通信協(xié)議的協(xié)議族,對于tcp/ip協(xié)議族,該參數(shù)置af_inet;type:指定要創(chuàng)建的套接字類型,流套接字類型為sock_stream、數(shù)據(jù)報套接字類型為sock_dgram;protocol:指定應(yīng)用程序所使用的通信協(xié)議,一般設(shè)置為0。該函數(shù)如果調(diào)用成功就返回新創(chuàng)建的套接字的描述符,套接字描述符是一個整數(shù)類型的值;如果失敗就返回-1。 綁定套接字#includeint bind(int socket, const struct sockaddr *address, size_t address_len);socket:由socket()調(diào)用返回的套接字描述符;addreess:結(jié)構(gòu)指針指向了與協(xié)議名稱和協(xié)議相關(guān)的信息;address_len:指明了address數(shù)據(jù)結(jié)構(gòu)的大小。如果調(diào)用成功,bind()函數(shù)返回0;否則返回-1,并設(shè)置錯誤代碼到errno。 等待客戶端連接服務(wù)器端應(yīng)用軟件通過調(diào)用accept()函數(shù)將自身阻塞,直至有新的客戶端連接。#includeint accept(int socket,struct sockaddr *address,socketlen_t address_len);socket:創(chuàng)建并綁定的套接字;address:返回連接服務(wù)器的客戶端地址信息;address_len:指明了address數(shù)據(jù)結(jié)構(gòu)的大小。如果調(diào)用成功,則返回非負(fù)的連接套接字;否則返回-1,并設(shè)置錯誤代碼到errno。 連接服務(wù)器客戶端通過connect()函數(shù)和服務(wù)器進(jìn)行tcp連接。#include int connect(int socket, const struct sockaddr *address, size_t address_len);socket:創(chuàng)建并綁定套接字;address:指明要連接服務(wù)器的ip地址和端口號;address_len:指明了address數(shù)據(jù)結(jié)構(gòu)的大小。如果調(diào)用成功,返回0;否則返回-1,并設(shè)置錯誤代碼到errno。 udp協(xié)議的發(fā)送數(shù)據(jù)udp協(xié)議需要通過sendto()函數(shù)實現(xiàn)一個數(shù)據(jù)包的發(fā)送,這是因為udp協(xié)議提供的是以數(shù)據(jù)包為單位的傳輸,而tcp協(xié)議提供的是以字節(jié)流為單位的傳輸。#includessize_t sendto(int socket,const void*message,size_t length,int flags,const struct sockaddr*dest_addr,socklen_t dest_len);socket:已經(jīng)創(chuàng)建的套接字;message:指明要發(fā)送的數(shù)據(jù)包的地址;length:數(shù)據(jù)包大??;flags:設(shè)置發(fā)送的屬性,一般可設(shè)置為0;dest_addr:指明目的端的ip地址和端口號;dest_len:指明dest_addr數(shù)據(jù)結(jié)構(gòu)的大小。如果調(diào)用成功,返回實際發(fā)送的數(shù)據(jù)數(shù)目;否則返回-1,并設(shè)置錯誤代碼到errno。 udp協(xié)議的接收數(shù)據(jù)udp協(xié)議需要通過recvfrom()函數(shù)接收一個數(shù)據(jù)包。#includessize_t recvfrom(int socket,void* buffer,size_t length,int flags,struct sockaddr* address,socklen_t address_len);socket:已經(jīng)創(chuàng)建的套接字;message:指明要接收的數(shù)據(jù)包的地址;length:數(shù)據(jù)包大?。籪lags:設(shè)置發(fā)送的屬性,一般可設(shè)置為0;dest_addr:指明目的端的ip地址和端口號;dest_len:指明dest_addr數(shù)據(jù)結(jié)構(gòu)的大小。如果調(diào)用成功,返回實際發(fā)送的數(shù)據(jù)數(shù)目;否則返回-1,并設(shè)置錯誤代碼到errno。 向一個已連接的套接口發(fā)送數(shù)據(jù)。#include ssize_t send(int socket, const char void* buffer, int length, int flags);socket:一個用于標(biāo)識已連接套接口的描述字;buffer:包含待發(fā)送數(shù)據(jù)的緩沖區(qū);length:緩沖區(qū)中數(shù)據(jù)的長度;flags:調(diào)用執(zhí)行方式;若無錯誤發(fā)生,send()返回所發(fā)送數(shù)據(jù)的總數(shù);否則的話,返回-1并把錯誤保存到errno。 從一個已連接的套接口接收數(shù)據(jù)。#include ssize_t recv( int socket, char * buffer, int length, int flags);socket:一個標(biāo)識已連接套接口的描述字;buffer:用于接收數(shù)據(jù)的緩沖區(qū);length:緩沖區(qū)長度;flags:指定調(diào)用方式;若無錯誤發(fā)生,recv()返回讀入的字節(jié)數(shù)。如果連接已中止,返回0;否則的話,返回-1并把錯誤保存到errno。 ip地址的轉(zhuǎn)換和獲取在上述套接字程序設(shè)計中,服務(wù)器和客戶端的ipv4地址采用了32為無符號整數(shù)表示。在用戶方面,廣泛使用的是十進(jìn)制字符串表示(例如2)或者主機名稱(例如)。linux操作系統(tǒng)提供了一系列函數(shù)實現(xiàn)這幾種格式之間的轉(zhuǎn)換。#includein_addr_t inet_addr(char* cp);cp:指向十進(jìn)制字符串表示的ipv4地址。如果調(diào)用成功,返回ipv4地址的32位無符號整數(shù)表示;否則返回in_addr_t-l。 gethostbyname()函數(shù)可以實現(xiàn)從主機名稱到32位無符號整數(shù)表示的轉(zhuǎn)換。#includestruct hostent char *h_name; char *h_aliases; int h_addrtype; int h_length; char *h_addr_list;struct hostent *gethostbyname(const char *name);name:指明了主機名稱的字符串。如果調(diào)用成功,返回指向hostent的指針;否則返回null,并設(shè)置錯誤代碼到h_erno。其中hostent中的h_length指明了主機地址的長度,在ipv4協(xié)議下始終為1。h_addr_list指明了主機的所有網(wǎng)絡(luò)地址。一般情況下,h_addr_list0就表明了此主機ipv4地址的32位無符號整數(shù)表示。 gethostbyaddr()函數(shù)可以實現(xiàn)從32為無符號整數(shù)到主機名稱的轉(zhuǎn)換。#includestruct hostent *gethostbyaddr(const void *addr,socklen_t len,int type);addr:指明了32位無符號整數(shù)表示的ipv4地址;len:指明了地址長度;type:在ipv4協(xié)議下,可以設(shè)置為af_inet。如果調(diào)用成功,返回指向hostent的指針;否則返回null,并設(shè)置錯誤代碼到h_errno。 線程創(chuàng)建函數(shù)#includeint pthread_create(pthread_t *thread,pthread_ayyr_t *attr,void*(*start_routine)(void *),void *arg)thread:這是一個指向pthread_t類型數(shù)據(jù)的指針。線程被創(chuàng)建時,這個指針指向的變量中將被寫入一個標(biāo)識符,我們用該標(biāo)識符來引用線程。attr:這個參數(shù)一般用于設(shè)置線程的屬性,我們一般不需要設(shè)置特殊的屬性,所以可以簡單的設(shè)置該參數(shù)為null。start_routine :這個參數(shù)告訴線程將要啟動的函數(shù)。arg:這個參數(shù)將傳遞啟動函數(shù)的參數(shù) 。二、tcp/udp開發(fā)簡介1、tcp開發(fā)介紹在基于tcp協(xié)議的程序設(shè)計中一般采用客戶端/服務(wù)器的程序設(shè)計模式。在服務(wù)器端首先使用socket()函數(shù)創(chuàng)建套接字,然后使用bind()函數(shù)將本機ip地址和服務(wù)端口綁定至套接字,并通過listen()函數(shù)建立等待隊列,隨后就可以使用accept()函數(shù)等待客戶端的連接。accept()函數(shù)將一直阻塞,直至有一個客戶端連接到本地服務(wù)器端口為止。該函數(shù)將返回一個新的套接字值,隨后服務(wù)器就可以通過新的套接字接口與連接上的客戶端利用rend()或write()函數(shù)進(jìn)行交互??蛻舳嗽谠L問服務(wù)器時首先要通過socket()函數(shù)調(diào)用,然后通過connect()函數(shù)連接服務(wù)器的ip地址和相應(yīng)的服務(wù)器端口號。連接成功后,就可以通過read()或者write()函數(shù)與服務(wù)器進(jìn)行數(shù)據(jù)交互了。客戶端/服務(wù)器結(jié)構(gòu)下的tcp應(yīng)用程序框架如圖所示5:socket():創(chuàng)建套接字bind():綁定本機地址和端口號listen():設(shè)置等待隊列accept():等待客戶端連接sendto()和recv()與客戶端交換數(shù)據(jù)close()關(guān)閉特定客戶端套接字socket:創(chuàng)建套接字connect()連接服務(wù)器sendto()和recv()與服務(wù)器端交換數(shù)據(jù)close()關(guān)閉套接字建立請求圖2.1客戶端/服務(wù)器結(jié)構(gòu)下的tcp協(xié)議程序結(jié)構(gòu)圖2、udp開發(fā)介紹基于udp協(xié)議的應(yīng)用程序設(shè)計比較簡單。首先通信雙方都要利用socket()函數(shù)創(chuàng)建套接字,然后將本機ip地址和端口通過bind()函數(shù)與套接字綁定。綁定后,可以直接使用sendto()函數(shù)向?qū)Ψ桨l(fā)送消息。使用recvfrom()函數(shù)可以接收指定端口的udp包,并通過返回的address結(jié)構(gòu)獲知發(fā)送方的ip地址和端口號。第四節(jié) 本章小結(jié)本章主要介紹了該系統(tǒng)開發(fā)的環(huán)境和平臺,linux是一款流行的網(wǎng)絡(luò)操作系統(tǒng),由unix演化了來,具有豐富和網(wǎng)絡(luò)功能,開發(fā)的函數(shù)庫較多,功能強大。gcc是一款開源的編譯器,有強大的編譯調(diào)試的能力,使本系統(tǒng)的開發(fā)、測試,輕松了很多。最后介紹了本章的網(wǎng)絡(luò)編程的一些知識,包括tcp/udp技術(shù)檢測和一些系統(tǒng)開發(fā)用到的socket函數(shù)。第三章 系統(tǒng)的分析與設(shè)計第一節(jié) 需求分析一、問題定義本系統(tǒng)的問題概述如下:基本問題是linux以及網(wǎng)絡(luò)編程的研究,基本目標(biāo)是設(shè)計一個基于linux環(huán)境的心跳檢測的系統(tǒng)來判斷局域網(wǎng)的網(wǎng)絡(luò)連接是否正常。 二、可行性研究可行性分析的任務(wù)不是研究如何解決問題,而是要用最小的代價在最短的時間內(nèi),確定問題定義階段所定義的問題是否值得解決。一般情況下,主要從技術(shù)可行性、經(jīng)濟可行性和操作可行性三個方面論證系統(tǒng)開發(fā)的可行性。該系統(tǒng)可在小范圍的局域網(wǎng)上進(jìn)行使用,因此從可操作性來講是可行的。其次,設(shè)計開發(fā)這樣的一款心跳檢測系統(tǒng)只需要幾臺電腦構(gòu)成局域網(wǎng)就可以使用。下面主要從技術(shù)可行性進(jìn)行分析:開發(fā)工具和環(huán)境linux是一款比較成熟的操作系統(tǒng),它有unix演化發(fā)展而來,和unix有多相似之處。所用的函數(shù)包基本一致,再加上gcc的強大編譯、調(diào)試的功能,對完成這個系統(tǒng)由很大幫助。 算法該系統(tǒng)不需要什么復(fù)雜的算法,只需掌握linux環(huán)境下的tcp/ip網(wǎng)絡(luò)方面的知識,能夠熟練運用linux下的網(wǎng)絡(luò)編程和線程函數(shù),就可以寫出。幸運的是,通過查閱大量豐富的技術(shù)資料,我有信心解決這一問題。 自身素質(zhì)因素通過大學(xué)四年的學(xué)習(xí),我打下了堅實的專業(yè)基礎(chǔ),最重要的是學(xué)會了自主學(xué)習(xí)和查閱資料的能力,這都將為我今后的設(shè)計開發(fā)過程提供強有力的保障。通過以上分析,可以很確定這一系統(tǒng)的可行性,可以放心地開始下一階段的任務(wù)了。三、用戶需求本系統(tǒng)分為外圍節(jié)點和主控節(jié)點的設(shè)計,它們有各自的功能:1、外圍節(jié)點功能 外圍節(jié)點所需要完成的功能相對簡單,它只需要先發(fā)送登錄報文進(jìn)行注冊,收到主控節(jié)點的反饋報文之后,定期(每隔一秒)發(fā)送心跳報文即可,不涉及太多功能。2、主控節(jié)點功能 主控節(jié)點是系統(tǒng)的關(guān)鍵部分,它負(fù)責(zé)接收登錄報文和心跳報文,然后根據(jù)報文的內(nèi)容來判斷網(wǎng)絡(luò)連接情況,可以說本系統(tǒng)的主要功能基本上由主控節(jié)點完成:完成接收心跳報文功能主控節(jié)點收到外圍節(jié)點的登錄報文后,就完成對外圍節(jié)點信息的注冊,包括外圍節(jié)點的設(shè)備號和分配的槽口號等,并將槽口號返回給外圍節(jié)點。完成接收心跳報文功能主控節(jié)點接收到心跳報文后,由于心跳報文中帶有槽口號,主控節(jié)點根據(jù)槽口號查找外圍節(jié)點注冊表,修改響應(yīng)信息。完成定期檢查外圍節(jié)點功能 主控節(jié)點要定期檢查外圍節(jié)點注冊表,從而發(fā)現(xiàn)節(jié)點是否正常工作,如果不正常就報告響應(yīng)的故障消息。四、系統(tǒng)整體用例圖圖3.1 系統(tǒng)用例圖第二節(jié) 概要設(shè)計概括地說,概要設(shè)計進(jìn)行數(shù)據(jù)設(shè)計/數(shù)據(jù)庫設(shè)計和系統(tǒng)體系結(jié)構(gòu)設(shè)計。其目的只是描繪出軟件的總體框架,根據(jù)功能、性能需求和數(shù)據(jù)需求導(dǎo)出軟件的數(shù)據(jù)結(jié)構(gòu)和系統(tǒng)結(jié)構(gòu)。一、設(shè)計指導(dǎo)思想 模塊化模塊是構(gòu)成程序的基本構(gòu)件,模塊化就是把程序劃分成獨立命名且可獨立訪問的模塊,每個模塊完成一個子功能,把這些模塊集成起來就構(gòu)成了一個整體,可以完成指定的功能,以滿助于用戶需求。采用模塊化原理可以使軟件結(jié)構(gòu)清晰,降低了系統(tǒng)的復(fù)雜性,使系統(tǒng)容易設(shè)計、容易修改,而且其推動了系統(tǒng)各部分的并行開發(fā),提高了軟件的生產(chǎn)效率。本心跳檢測系統(tǒng)設(shè)計正是采用了模塊化原理,在主控節(jié)點上有三個線程,每個線程看做一個模塊,方便了主控節(jié)點功能的實現(xiàn)。 抽象化在對軟件系統(tǒng)進(jìn)行模塊設(shè)計時,可以有不同的抽象層次,系統(tǒng)設(shè)計過程中的每一步都是對軟件問題解法的又一次更高級抽象??尚行匝芯渴菍φ麄€系統(tǒng)的抽象,需求分析則是對此心跳檢測系統(tǒng)所要實現(xiàn)功能的抽象。二、心跳檢測系統(tǒng)的整體結(jié)構(gòu)圖使用上節(jié)所提到的模塊化等設(shè)計思想,先是對外圍節(jié)點的發(fā)送報文的流程進(jìn)行了設(shè)計,然后說對主控節(jié)點的完成外圍節(jié)點注冊,完成接收心跳報文,完成定期檢查外圍節(jié)點三個功能進(jìn)行了一一的設(shè)計,下面是整個程序的結(jié)構(gòu)圖,如圖3.2示。圖3.2 程序結(jié)構(gòu)圖三、總體設(shè)計心跳檢測的基本原理是每個結(jié)點周期性地向主控節(jié)點發(fā)送消息,主控節(jié)點根據(jù)外圍節(jié)點發(fā)送來的消息判斷這些節(jié)點的狀態(tài)。整個心跳檢測系統(tǒng)包括外圍節(jié)點和主控節(jié)點兩個部分,其結(jié)構(gòu)如圖3.3所示。心跳檢測過程包括以下幾個步驟:連接的建立 外圍節(jié)點啟動,將首先與事先約定的主控節(jié)點ip地址建立tcp連接,并向主控節(jié)點注冊該外圍節(jié)點的設(shè)備號信息。主控節(jié)點在接收到外圍節(jié)點的注冊報文后,將回送許可報文。外圍節(jié)點在接收到許可報文后,將進(jìn)入心跳檢測狀態(tài)。如果外圍節(jié)點在5秒內(nèi)沒有連接到主控節(jié)點,或者發(fā)出注冊報文后5秒內(nèi)沒有收到主控節(jié)點的許可報文,則睡眠10秒鐘后重新與主控節(jié)點進(jìn)行連接。心跳檢測 外圍節(jié)點每隔1秒向主控節(jié)點發(fā)送一次心跳報文。主控節(jié)點每隔1秒查詢各個節(jié)點的心跳報文,如果在1秒內(nèi)沒有收到外圍節(jié)點的心跳報文,則顯示相應(yīng)外圍節(jié)點的網(wǎng)絡(luò)連接出現(xiàn)問題。 圖3.3心跳檢測的結(jié)構(gòu)圖外圍節(jié)點與主控節(jié)點建立連接時采用了tcp協(xié)議,而心跳檢測過程中使用了udp協(xié)議。這是由于tcp協(xié)議可以保證傳輸?shù)目煽啃院晚樞蛐?,但是運行開銷比較高,而udp協(xié)議雖然是一中不可靠的協(xié)議,但是傳輸開銷比較小。因此,在嵌入式系統(tǒng)中,為了降低系統(tǒng)運行開銷,可以將一些不重要的報文采用代繳比較低但是服務(wù)質(zhì)量比較查的協(xié)議來實現(xiàn)。第三節(jié) 詳細(xì)設(shè)計 詳細(xì)設(shè)計是該系統(tǒng)的重點部分,介紹了系統(tǒng)具體是如何實現(xiàn)的,包括了心跳注冊表的設(shè)計,報文格式的設(shè)計,主控節(jié)點和外圍節(jié)點功能的設(shè)計。一、心跳表注冊表的設(shè)計心跳注冊表被設(shè)置成一個靜態(tài)全局的結(jié)構(gòu)體數(shù)組,當(dāng)主控節(jié)點接收到外圍節(jié)點的注冊報文之后就為其在心跳注冊表中找到一個空閑位置分配。而此后,主控節(jié)點在接收到外圍節(jié)點的心跳報文后,也要相應(yīng)的修改心跳注冊表,判斷節(jié)點是否出現(xiàn)故障也是通過掃描心跳注冊表得知,所以這是個很關(guān)鍵的設(shè)計。結(jié)構(gòu)體如下: struct heart_beatchar state;char flag;unsigned int device_id;struct sockaddr_in addr;#define heart_beat_table_size 64static struct heart_beat hb_tableheart_beat_table_size;表3.1statestate有idle和busy兩種狀態(tài),各自的定義如下: #define idle 0#define busy 1只有設(shè)備正常工作時state才為busy,否則為idle。flagflag在主控節(jié)點接收到外圍節(jié)點的心跳報文后設(shè)置為1,在檢測心跳表判斷設(shè)備是否工作時重新設(shè)置為0,用于標(biāo)記外圍節(jié)點是否壞掉。device_iddevice_id 是外圍節(jié)點注冊時向主控節(jié)點提供的,用于標(biāo)識每個設(shè)備。sockaddr_in addrsockaddr_in addr是外圍節(jié)點的ip地址。主控節(jié)點對心跳注冊表的具體操作如下: 圖3.4主控節(jié)點對心跳注冊表的操作二、報文格式的設(shè)計主控節(jié)點和外圍節(jié)點之間有三種報文:從外圍節(jié)點到主控節(jié)點的登錄報文(login),從主控節(jié)點到外圍節(jié)點的響應(yīng)報文(respond),以及從外圍節(jié)點到主控節(jié)點的心跳報文(heart_beat)。其中前兩者通過tcp協(xié)議發(fā)送,后者通過udp協(xié)議發(fā)送。在每種類型的報文前均有一個惟一的字節(jié)標(biāo)識type,用于標(biāo)識不同類型的報文。例如,在登錄報文中,其type值為1;在響應(yīng)報文中,其type值為2等。之所以采用這樣的方法,是考慮到未來報文類型擴展的需要。由于各種報文均通過一個tcp端口接收,而接收端應(yīng)用程序事先無法知道已經(jīng)被操作系統(tǒng)接收的報文種類,因此也無法判斷應(yīng)該從recv()函數(shù)接口中讀取多少字節(jié)。為了解決這一問題,接收端一般應(yīng)該首先接收第一個字節(jié),以判斷當(dāng)前報文的類型,然后根據(jù)此類型的大小決定從操作系統(tǒng)內(nèi)存讀取多少個字節(jié)到應(yīng)用程序的數(shù)據(jù)結(jié)構(gòu)中,以得到一個完整的報文。這三種報文格式為:#define login_type 0x01#define respond_type 0x02#define heart_beat_type 0x03登錄報文:struct login char type;unsigned int device_id;表3.2type登錄報文的type為0x01device_id外圍節(jié)點注冊時提供的設(shè)備號登錄報文是外圍節(jié)點向主控節(jié)點進(jìn)行注冊信息時,通過tcp連接發(fā)送的,外圍節(jié)點需要提供自己的設(shè)備號即可,主控節(jié)點修改心跳注冊表完成對外圍節(jié)點的注冊。響應(yīng)報文:struct respond char type;int index;表3.3type登錄報文的type為0x02index主控節(jié)點接收到外圍節(jié)點注冊成功時2提供給外圍節(jié)點的槽口號主控節(jié)點收到外圍節(jié)點的登錄報文之后,必須要對外圍節(jié)點進(jìn)行響應(yīng),這時就需要發(fā)送具有反饋信息的respond報文,該報文包含了外圍節(jié)點注冊信息表給該外圍節(jié)點提供槽口號index(第一個注冊的為0,第二個注冊的為1,一次類推),外圍節(jié)點必須收到respond報文后才可以開始發(fā)送心跳報文。心跳報文:struct heart_beat char type;int index;unsigned int device_id;表3.4type登錄報文的type為0x03index主控節(jié)點接收到外圍節(jié)點注冊成功時2提供給外圍節(jié)點的槽口號,發(fā)送心跳報文時需提供槽口號以便主控節(jié)點修改hb_table表device_id外圍節(jié)點注冊時提供的設(shè)備號 心跳報文是外圍節(jié)點定期向主控節(jié)點發(fā)送的udp報文,包含了外圍節(jié)點的設(shè)備號和槽口號,主控節(jié)點根據(jù)槽口號來修改外圍節(jié)點注冊信息表,從而為定期掃描心跳注冊表做準(zhǔn)備。三、外圍節(jié)點的設(shè)計心跳檢測是外圍節(jié)點軟件系統(tǒng)中的一個模塊。它被設(shè)計成一個獨立的線程,執(zhí)行如下算法:向主控節(jié)點發(fā)送登錄(login)報文等待主控節(jié)點的反饋(respond)報文的響應(yīng) 接收到respond報文轉(zhuǎn)向4,否則休眠10秒后轉(zhuǎn)向1根據(jù)respond報文的槽口號建立udp連接 向主控節(jié)點發(fā)送udp心跳報文 休眠1秒后轉(zhuǎn)向5創(chuàng)建心跳檢測線程其他處理建立與主的tcp連接向主機發(fā)送登錄信息接受主機分配的槽口號通過udp協(xié)議發(fā)送心跳報文休眠10秒休眠100毫秒連接成功是否圖3.5外圍節(jié)點程序結(jié)構(gòu)圖2、外圍節(jié)點的時序圖3.6外圍節(jié)點的時序圖四、主控節(jié)點的設(shè)計 主控節(jié)點完成的功能比較復(fù)雜,包括接收外圍節(jié)點的登錄報文,接收外圍節(jié)點的心跳報文,定期進(jìn)行檢查心跳注冊表等??梢钥紤]采用三個線程分別實現(xiàn)這些功能,并通過一個共享的外圍節(jié)點心跳表進(jìn)行交互。 外圍節(jié)點心跳表的數(shù)據(jù)結(jié)構(gòu)如下所示。 #define idle 0#define busy 1#define heart_beat_table_size 64#define no_device 0struct heart_beatchar state;char flag;unsigned int device_id;struct sockaddr_in addr;static struct heart_beat hb_tableheart_beat_table_size;主控節(jié)點程序啟動后,將首先初始化互斥量hb_table_lock,初始化hb_table數(shù)組中各個元素的state狀態(tài)idle,然后創(chuàng)建三個線程。執(zhí)行函數(shù)分別是accept_connect(),chenk_hb(),accept_hb()三個線程的結(jié)構(gòu)圖如下:圖3.7 主控節(jié)點線程調(diào)用關(guān)系圖1、 接收登錄線程接收登錄信息的線程執(zhí)行如下算法: 創(chuàng)建套接字,綁定登錄端口,并建立等待隊列。 使用accept()函數(shù)等待外圍節(jié)點的登錄信息。 從套接字端口讀取登錄報文,獲取外圍節(jié)點的設(shè)備號device_id和ip地址。 檢查hb_table中的各個表項。 如果當(dāng)前設(shè)備號device_id已經(jīng)存在于此表,且相關(guān)的狀態(tài)為busy,則取此表項號index;否則分配一個state為idle的表項index。 設(shè)置hb_tableindex表項中的state為busy,設(shè)置此表項中的device_id何addr為外圍設(shè)備的device_id和ip地址,設(shè)置此表項中的

溫馨提示

  • 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)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論