軟件工程-課程設(shè)計-Socket聊天系統(tǒng)_第1頁
軟件工程-課程設(shè)計-Socket聊天系統(tǒng)_第2頁
軟件工程-課程設(shè)計-Socket聊天系統(tǒng)_第3頁
軟件工程-課程設(shè)計-Socket聊天系統(tǒng)_第4頁
軟件工程-課程設(shè)計-Socket聊天系統(tǒng)_第5頁
已閱讀5頁,還剩38頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

Socket聊天系統(tǒng)計科10102班35劉衛(wèi)軍 目錄TOC\o"1-3"\h\u92291.前言 437292.需求分析 585452.1系統(tǒng)的功能需求 590312.1.4點歌 567202.1.5分組管理 5318142.1.6個人信息管理 527082.1.7用戶管理 5263662.1.8視頻通話 536962.2非功能需求: 5107442.2.2網(wǎng)絡(luò)安全 525542.3用例分析 6229302.3.1參與者 6178222.3.2用例分析 6132962.3.3系統(tǒng)的用例圖 6186363.總體設(shè)計 8177103.1TCP服務(wù)器設(shè)置 8204433.2分析類圖 9241403.3順序圖 10240003.2.1用戶私聊順序圖 10318663.2.2用戶傳送文件序列圖 11124743.3協(xié)作圖 11275543.3.1用戶私聊協(xié)作圖 11228193.3.2用戶傳送文件協(xié)作圖 1216364.詳細設(shè)計 14276534.1客戶端設(shè)計 14181504.2服務(wù)端設(shè)計 14223124.3多線程設(shè)計 15141125.代碼實現(xiàn) 16191195.1服務(wù)端設(shè)計 1611665.2客戶端設(shè)計 1832005.3多線程 22231495.3.1服務(wù)端多線程 22276585.3.2客戶端多線程 24324996.運行與測試 252986.1用戶登錄界面 25212756.2輸入端口界面 25305226.3服務(wù)器記錄,在線的用戶信息。 2646036.4私聊 26280456.4.1登錄 26214506.4.2用戶給指定的好友發(fā)送信息。(私聊) 272346.4.3指定好友接受到好友信息。(私聊的信息) 27148376.4.5好友回復(fù)我的信息 28281006.5群聊 2853646.5.1發(fā)送群消息 28310376.5.2好友響應(yīng)并接受群聊信息 296596 29325697.小結(jié) 30113108.參考文獻 311.前言 隨著互聯(lián)網(wǎng)的快速發(fā)展,網(wǎng)絡(luò)聊天工具已經(jīng)作為一種重要的信息交流工具,受到越來越多的網(wǎng)民的青睞。目前,出現(xiàn)了很多非常不錯的聊天工具,其中應(yīng)用比較廣泛的有Netmeeting、騰訊QQ、MSN-Messager等等。該系統(tǒng)開發(fā)主要包括一個網(wǎng)絡(luò)聊天服務(wù)器程序和一個網(wǎng)絡(luò)聊天客戶程序兩個方面。前者通過Socket套接字建立服務(wù)器,服務(wù)器能讀取、轉(zhuǎn)發(fā)客戶端發(fā)來信息,并能刷新用戶列表。后者通過與服務(wù)器建立連接,來進行客戶端與客戶端的信息交流。其中用到了局域網(wǎng)通信機制的原理,通過直接繼承Thread類來建立多線程。開發(fā)中利用了計算機網(wǎng)絡(luò)編程的基本理論知識,如TCP/IP協(xié)議、客戶端/服務(wù)器端模式(Client/Server模式)、網(wǎng)絡(luò)編程的設(shè)計方法等。在網(wǎng)絡(luò)編程中對信息的讀取、發(fā)送,是利用流來實現(xiàn)信息的交換,其中介紹了對實現(xiàn)一個系統(tǒng)的信息流的分析,包含了一些基本的軟件工程的方法。經(jīng)過分析這些情況,該局域網(wǎng)聊天工具采用Eclipse為基本開發(fā)環(huán)境和java語言進行編寫,首先可在短時間內(nèi)建立系統(tǒng)應(yīng)用原型,然后,對初始原型系統(tǒng)進行不斷修正和改進,直到形成可行系統(tǒng)

本文通過java的Socket實現(xiàn)了一個基于局域網(wǎng)和網(wǎng)絡(luò)的聊天室的程序的開發(fā)基于java的C/S模式網(wǎng)絡(luò)聊天室的設(shè)計與實現(xiàn)。C/S(Client/Server)結(jié)構(gòu),即大家熟知的客戶機和服務(wù)器結(jié)構(gòu)。它是軟件系統(tǒng)體系結(jié)構(gòu),通過它可以充分利用兩端硬件環(huán)境的優(yōu)勢,將任務(wù)合理分配到Client端和Server端來實現(xiàn),降低了系統(tǒng)的通訊開銷。目前大多數(shù)應(yīng)用軟件系統(tǒng)都是Client/Server形式的兩層結(jié)構(gòu),由于現(xiàn)在的軟件應(yīng)用系統(tǒng)正在向分布式的Web應(yīng)用發(fā)展,Web和Client/Server

應(yīng)用都可以進行同樣的業(yè)務(wù)處理,應(yīng)用不同的模塊共享邏輯組件;因此,內(nèi)部的和外部的用戶都可以訪問新的和現(xiàn)有的應(yīng)用系統(tǒng),通過現(xiàn)有應(yīng)用系統(tǒng)中的邏輯可以擴展出新的應(yīng)用系統(tǒng)。這也就是目前應(yīng)用系統(tǒng)的發(fā)展方向。關(guān)鍵詞:聊天

客戶端

信息

服務(wù)器端

JavaC/S聊天系統(tǒng)

2.需求分析2.1系統(tǒng)的功能需求2.1.1實現(xiàn)私聊(一對一):在登陸的情況下選擇你要聊天的好友,進行信息的傳送,實現(xiàn)彼此的聊天,這也是本系統(tǒng)最基本的功能。2.1.2群聊(一對多):可以實現(xiàn)一對多人的聊天。2.1.3大文件傳輸:在能夠聊天的基礎(chǔ)上,實現(xiàn)通訊的多元化,進行文件的傳輸。是通訊雙方可以選擇傳送對方想獲得的資料。2.1.4點歌2.1.5分組管理2.1.6個人信息管理2.1.7用戶管理2.1.8視頻通話2.2非功能需求:2.2.1界面友好:界面易操作性,對經(jīng)典的聊天程序的界面進行了學習和借鑒,模仿他們的界面和常用的操作。2.2.2網(wǎng)絡(luò)安全加密解密為了提高傳輸?shù)陌踩?,進行加密操作。及時在網(wǎng)絡(luò)上被別人了竊聽消息,也不能得到原始信息,防止個人重要信息和隱私信息被盜。2.3用例分析2.3.1參與者本系統(tǒng)顯而易見的兩個參與者:用戶和管理員。2.3.2用例分析從上面的需求里進行抽象和提取關(guān)鍵信息,在確定系統(tǒng)邊界的情況下,選擇最基本的用例,然后對用例進行描述和細化。使其能完全的描述系統(tǒng)的功能性需求。2.3.3系統(tǒng)的用例圖通過對參與者和用例的分析,確定他們的關(guān)系(包括參與者和參與者的關(guān)系,參與者和用例的關(guān)系,用例之間的關(guān)系。)其中用例之間的關(guān)系是分析中的重點,如圖私聊和群聊都有socket聊天的模塊,所以可以確定的是包含關(guān)系。管理個人信息,包含了分組管理和用戶信息管理,其中分組管理和用戶信息管理,是個人信息管理的子集,所以應(yīng)該是泛化關(guān)系。在文件傳輸?shù)臅r候,可能會產(chǎn)生信息的丟失,導致信息不完整,接收方不能完整收到發(fā)送方的消息,所以導致發(fā)送方重發(fā)信息。所以這是擴展關(guān)系,因為只有在傳輸文件失敗的時候,才能啟用重傳文件的模塊。用戶所參與的模塊首先應(yīng)該登錄,在登錄系統(tǒng)后,可以私聊和群聊來交流信息。用戶可以管理自己的信息進行修改自己的信息和管理自己的分組。為了豐富系統(tǒng)的功能我,我們還特意實現(xiàn)了點歌功,和傳輸文件吸引用戶的眼光。 3.總體設(shè)計3.1TCP服務(wù)器設(shè)置在T

C

P

/

I

P協(xié)議族中,有兩個互不相同的傳輸協(xié)議:

T

C

P(傳輸控制協(xié)議)和U

D

P(用戶數(shù)據(jù)報協(xié)議)。T

C

P為兩臺主機提供高可靠性的數(shù)據(jù)通信。它所做的工作包括把應(yīng)用程序交給它的數(shù)據(jù)分成合適的小塊交給下面的網(wǎng)絡(luò)層,確認接收到的分組,設(shè)置發(fā)送最后確認分組的超時時鐘等。由于運輸層提供了高可靠性的端到端的通信,因此應(yīng)用層可以忽略所有這些細節(jié)。而另一方面,

U

D

P則為應(yīng)用層提供一種非常簡單的服務(wù)。它只是把稱作數(shù)據(jù)報的分組從一臺主機發(fā)到另一臺主機,但并不保證該數(shù)據(jù)報能到達另一端。任何必需的可靠性必須由應(yīng)用層來提供。Bind()Bind()Socket()Readfrom()等待客戶請求處理服務(wù)請求Sendto()Close()Socket()Bind()Sendto()Readfrom()Close()服務(wù)請求服務(wù)應(yīng)答服務(wù)器客戶機服務(wù)器和客戶機通訊流程3.2分析類圖(系統(tǒng)整齊的分析類圖)沒有類是單獨存在的,通常和別的類協(xié)作,創(chuàng)造比單獨工作更大的語義。因此,除了捕獲系統(tǒng)的詞匯以外,還要將注意力集中到這些類是如何在一起工作的。使用類圖來表達這種協(xié)作。確定你建模的機制。機制代表了部分你建模的系統(tǒng)的一些功能和行為,這些功能和行為是一組類、接口和其他事物相互作用的結(jié)果。對于每個機制,確定類、接口和其他的參與這個協(xié)作的協(xié)作。同時確定這些事物之間的關(guān)系。 用場景來預(yù)排這些事物,沿著這條路你將發(fā)現(xiàn)模型中忽略的部分和定義錯誤的部分。確定用這些事物的內(nèi)容來填充它們。對于類,開始于獲得一個責任(類的職責),然后,將它轉(zhuǎn)化為具體的屬性和方法。3.3順序圖3.2.1用戶私聊順序圖用戶在進入系統(tǒng)前首先要輸入彼此通訊的端口號,由于客戶機和服務(wù)器都是本機所以不需要尋找IP地址,然后輸入用戶名新建一個用戶,由于沒有保存歷史記錄功能,所以每次進入系統(tǒng)前都需要新建一個用戶。然后輸入用戶名和密碼,在確認用戶和密碼。登陸成功,選擇在線可以聊天的好友,輸入信息然后發(fā)送,達到和好友的交流。3.2.2用戶傳送文件序列圖3.3協(xié)作圖3.3.1用戶私聊協(xié)作圖強調(diào)的是發(fā)送和接收消息的對象之間的組織結(jié)構(gòu)。一個協(xié)作圖顯示了一系列的對象和在這些對象之間的聯(lián)系以及對象間發(fā)送和接收的消息。對象通常是命名或匿名的類的實例,也可以代表其他事物的實例。3.3.2用戶傳送文件協(xié)作圖用戶在登錄系統(tǒng)后,進入登陸界面,在界面的好友框里,選擇要傳送文件的好友,點擊傳送文件的按鈕,會彈出選擇文件的對話框,在對話框里查找你所在的文件系統(tǒng)中你要傳送的文件。然后點擊傳送。4.詳細設(shè)計4.1客戶端設(shè)計一個網(wǎng)絡(luò)聊天室的運行,首先是要有一個完整穩(wěn)定的服務(wù)器端,并且擁有很多個服務(wù)器端??头艘哂袑崿F(xiàn)用戶注冊和用戶登陸,在登陸成功后,要顯示出公聊界面,實現(xiàn)聊天功能并且能夠發(fā)送表情和保存聊天內(nèi)容和顯示聊天記錄等功能,在新用戶上線和用戶下線時要更新每個客戶端在線用戶列表名,并且可以和在線的用戶實現(xiàn)一對一的私聊功能。

在服務(wù)器端可以實現(xiàn)不斷的監(jiān)聽客服的連接,并且根據(jù)客戶端發(fā)送過來的不同信息如注冊信息,登錄信息,公聊信息,私聊信息,退出信息等,服務(wù)器端要做出不同的響應(yīng),并且要實現(xiàn)數(shù)據(jù)庫的操作,如根據(jù)用戶注冊的信息保存數(shù)據(jù)庫中,根據(jù)登錄時發(fā)送來的用戶名和密碼檢測是否合法用戶等。

經(jīng)為每一個連接著的客戶端建立了一個線程,這個線程好比一根電話線一直等待客戶端說話,而信息發(fā)送中心就相當于一個總臺,一旦有人打電話進來,就通過電話線把信息傳

完成了服務(wù)器端的第一個的任務(wù),那么第二個任務(wù)也就不難解決了。上面已送到總臺,再由總臺根據(jù)需要將這個信息發(fā)送給接收群。這樣

就意味著,服務(wù)器每接受一條信息,就要調(diào)用一次信息發(fā)送中心的方法,并將這條信息發(fā)送到所有客戶端(或者特定的某個/某幾個客戶端)。

電腦每做的一次動作,一個步驟,都是按照以經(jīng)用計算機語言編好的程序來執(zhí)行的,程序是計算機要執(zhí)行的指令的集合,而程序全部都是用我們所掌握的語言來編寫的。所以人們要控制計算機一定要通過計算機語言向計算機發(fā)出命令。

偵聽服務(wù)器發(fā)送的連接請求,有請求就接收發(fā)來的信息,并通過短信貓發(fā)出去

單的說,服務(wù)器端是為客戶端服務(wù)的,服務(wù)的內(nèi)容諸如向客戶端提供資源,保存客戶端數(shù)據(jù)等等.客戶端可以是任意的一臺電腦,只要它和服務(wù)器端存在連接,并且得到了服務(wù)器端的授權(quán),就可以使用服務(wù)器端的服務(wù).象現(xiàn)在就可以理解為百度的網(wǎng)站是服務(wù)器端,我們現(xiàn)在使用的電腦就是客戶端.我們可以使用它的服務(wù).

4.2服務(wù)端設(shè)計由于客戶端需要同時能夠接收信息以及發(fā)送信息,所以也必須利用多個線程來實現(xiàn)。主線程用于接收用戶輸入的內(nèi)容并將之發(fā)送到服務(wù)器端,而一個后臺線程將一直接收來自服務(wù)器端的信息,并將之返回給客戶端的用戶。

客戶端(Client)或稱為用戶端,是指與服務(wù)器相對應(yīng),為客戶提供本地服務(wù)的程序。除了一些只在本地運行的應(yīng)用程序之外,一般安裝在普通的客戶機上,需要與服務(wù)端互相配合運行。因特網(wǎng)發(fā)展以后,較常用的用戶端包括了如萬維網(wǎng)使用的網(wǎng)頁瀏覽器,收寄電子郵件時的電子郵件客戶端,以及即時通訊的客戶端軟件等。對于這一類應(yīng)用程序,需要網(wǎng)絡(luò)中有相應(yīng)的服務(wù)器和服務(wù)程序來提供相應(yīng)的服務(wù),如數(shù)據(jù)庫服務(wù),電子郵件服務(wù)等等,這樣在客戶機和服務(wù)器端,需要建立特定的通信連接,來保證應(yīng)用程序的正常運行。

不過客戶端及伺服端的關(guān)系不見得一定建立在兩臺分開的機器上,同一臺機器中也有這種主從關(guān)系的存在。提供服務(wù)的伺服端及接受服務(wù)的客戶端也有可能都在同一臺機器上,例如我們在提供網(wǎng)頁的服務(wù)器上執(zhí)行瀏覽器瀏覽本機所提供的網(wǎng)頁,這樣在同一臺機器上就同時扮演伺服端及客戶端。4.3多線程設(shè)計 為了能實現(xiàn)一對多的通話聊天也就是說間接的多對多的聊天的功能,所以必須在客戶端配置和服務(wù)端配置的時候。實現(xiàn)多線程的功能。實現(xiàn)程序的并發(fā)。以及可以減少創(chuàng)建進程是CPU的資源浪費。和服務(wù)區(qū)負荷太重。 多線程在客戶端可以實現(xiàn),用戶進行群聊,以及接受多個好友的響應(yīng)信息。在服務(wù)端可以減少創(chuàng)建進程的開銷。在一個程序中,這些獨立運行的程序片斷叫作“線程”(Thread),利用它編程的概念就叫作“多線程處理”。多線程處理一個常見的例子就是用戶界面。利用線程,用戶可按下一個按鈕,然后程序會立即作出響應(yīng),而不是讓用戶等待程序完成了當前任務(wù)以后才開始響應(yīng)。使用線程可以把占據(jù)時間長的程序中的任務(wù)放到后臺去處理用戶界面可以更加吸引人,這樣比如用戶點擊了一個按鈕去觸發(fā)某些事件的處理,可以彈出一個進度條來顯示處理的進度。程序的運行速度可能加快,在一些等待的任務(wù)實現(xiàn)上如用戶輸入、文件讀寫和網(wǎng)絡(luò)收發(fā)數(shù)據(jù)等,線程就比較有用了。在這種情況下可以釋放一些珍貴的資源如內(nèi)存占用等等。但是如果有大量的線程,會影響性能,因為操作系統(tǒng)需要在它們之間切換。更多的線程需要更多的內(nèi)存空間。線程可能會給程序帶來更多“bug”,因此要小心使用。線程的中止需要考慮其對程序運行的影響。通常塊模型數(shù)據(jù)是在多個線程間共享的,需要防止線程死鎖情況的發(fā)生。5.代碼實現(xiàn)5.1服務(wù)端設(shè)計publicclassServerFrameextendsJFrame{ privateJPanelcontentPane; privateJTextFieldtxtPort; privateJLabellblState; privateJTextAreatxtAllUsers; //集合:用來保存所有登錄的用戶 privateList<UserInfo>allLoginUser=null; publicstaticvoidmain(String[]args){ EventQueue.invokeLater(newRunnable(){ publicvoidrun(){ try{ ServerFrameframe=newServerFrame(); //禁止用戶更改窗體的大小 frame.setResizable(false); //距中 frame.setLocationRelativeTo(null); frame.setVisible(true); }catch(Exceptione){ e.printStackTrace(); } } }); } publicServerFrame(){ allLoginUser=newArrayList<UserInfo>(); initComponet(); } publicList<UserInfo>getAllLoginUser(){ returnallLoginUser; } publicvoidsetAllLoginUser(List<UserInfo>allLoginUser){ this.allLoginUser=allLoginUser; } privatevoidinitComponet(){ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100,100,449,506); contentPane=newJPanel(); contentPane.setBorder(newEmptyBorder(5,5,5,5)); setContentPane(contentPane); contentPane.setLayout(null); JPanelpanel=newJPanel(); panel.setBorder(newTitledBorder(UIManager .getBorder("TitledBorder.border"), "\u670D\u52A1\u5668\u4FE1\u606F",TitledBorder.LEADING, TitledBorder.TOP,null,newColor(0,70,213))); panel.setBounds(10,10,421,143); contentPane.add(panel); panel.setLayout(null); JLabellabel=newJLabel("\u670D\u52A1\u5668\u72B6\u6001\uFF1A"); label.setBounds(48,38,81,23); panel.add(label); lblState=newJLabel("Newlabel"); lblState.setBounds(161,42,110,15); panel.add(lblState); JLabellabel_1=newJLabel("\u670D\u52A1\u5668\u7AEF\u53E3\uFF1A"); label_1.setBounds(48,87,81,15); panel.add(label_1); txtPort=newJTextField(); txtPort.setBounds(161,84,110,21); panel.add(txtPort); txtPort.setColumns(10); JButtonbtnStart=newJButton("\u542F\u52A8\u670D\u52A1\u5668"); btnStart.addActionListener(newActionListener(){ publicvoidactionPerformed(ActionEvente){ try{ startServer(e); }catch(IOExceptione1){ //TODOAuto-generatedcatchblock e1.printStackTrace(); } } }); btnStart.setBounds(289,83,93,23); panel.add(btnStart); JPanelpanel_1=newJPanel(); panel_1.setBorder(newTitledBorder(null, "\u5DF2\u7ECF\u767B\u5F55\u7684\u7528\u6237", TitledBorder.LEADING,TitledBorder.TOP,null,null)); panel_1.setBounds(20,163,411,299); contentPane.add(panel_1); panel_1.setLayout(newBorderLayout(0,0)); txtAllUsers=newJTextArea(); panel_1.add(txtAllUsers,BorderLayout.CENTER); } publicvoidupdateGui(){ this.txtAllUsers.setText(null); for(inti=0;i<this.allLoginUser.size();i++){ this.txtAllUsers.append(allLoginUser.get(i).getUserName()); this.txtAllUsers.append("\n"); } } protectedvoidstartServer(ActionEvente)throwsIOException{ //驗證:是否為空的驗證 if(CommValidate.isEmpty(txtPort.getText())){ JOptionPane.showMessageDialog(null,"端口號不能空"); return; } //端口必須是數(shù)字 if(!CommValidate.isDigit(txtPort.getText())){ JOptionPane.showMessageDialog(null,"端口號必須是數(shù)字"); return; } //1024之上 //建立一個監(jiān)聽socket intport=Integer.parseInt(txtPort.getText()); ServerSocketserverSocket=newServerSocket(port); ServerListerenThreadserverListeren=newServerListerenThread( serverSocket,this); this.lblState.setOpaque(true); this.lblState.setForeground(Color.red); this.txtPort.setEnabled(false);//禁用 }}5.2客戶端設(shè)計publicclassClientLoginextendsJFrame{ privateJPanelcontentPane; privateJTextFieldtxtLoginUser; privateJTextFieldtxtAddress; privateJTextFieldtxtPort; privateSocketsocket; //登錄用戶信息 privateUserInfologinUser=null; publicUserInfogetLoginUser(){ returnloginUser; } publicvoidsetLoginUser(UserInfologinUser){ this.loginUser=loginUser; } publicSocketgetSocket(){ returnsocket; } publicvoidsetSocket(Socketsocket){ this.socket=socket; } privateServerSocketserverSocket; publicstaticvoidmain(String[]args){ EventQueue.invokeLater(newRunnable(){ publicvoidrun(){ try{ ClientLoginframe=newClientLogin(); frame.setAlwaysOnTop(true); frame.setResizable(false); frame.setVisible(true); }catch(Exceptione){ e.printStackTrace(); } } }); } publicClientLogin(){ initComponet(); } privatevoidinitComponet(){ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100,100,397,298); contentPane=newJPanel(); contentPane.setBorder(newEmptyBorder(5,5,5,5)); setContentPane(contentPane); contentPane.setLayout(null); JPanelpanel=newJPanel(); panel.setBorder(newTitledBorder(null,"\u7528\u6237\u767B\u5F55", TitledBorder.LEADING,TitledBorder.TOP,null,null)); panel.setBounds(10,10,369,244); contentPane.add(panel); panel.setLayout(null); JLabellabel=newJLabel("\u7528\u6237\u540D\uFF1A"); label.setBounds(37,36,54,15); panel.add(label); txtLoginUser=newJTextField(); txtLoginUser.setBounds(145,33,140,21); panel.add(txtLoginUser); txtLoginUser.setColumns(10); JLabellabel_1=newJLabel("\u670D\u52A1\u5668\u5730\u5740\uFF1A"); label_1.setBounds(37,80,98,15); panel.add(label_1); txtAddress=newJTextField(); txtAddress.setText("localhost"); txtAddress.setBounds(145,77,140,21); panel.add(txtAddress); txtAddress.setColumns(10); JLabellabel_2=newJLabel("\u7AEF\u53E3\u53F7\uFF1A"); label_2.setBounds(37,120,54,15); panel.add(label_2); txtPort=newJTextField(); txtPort.setText("5555"); txtPort.setBounds(145,117,140,21); panel.add(txtPort); txtPort.setColumns(10); JButtonbtnLogin=newJButton("\u767B\u5F55"); btnLogin.addActionListener(newActionListener(){ publicvoidactionPerformed(ActionEvente){ try{ login(e); }catch(UnknownHostExceptione1){ //TODOAuto-generatedcatchblock e1.printStackTrace(); }catch(IOExceptione2){ //TODOAuto-generatedcatchblock e2.printStackTrace(); }catch(ClassNotFoundExceptione3){ //TODOAuto-generatedcatchblock e3.printStackTrace(); } } }); btnLogin.setBounds(69,164,93,23); panel.add(btnLogin); JButtonbtnReset=newJButton("\u91CD\u7F6E"); btnReset.setBounds(192,164,93,23); panel.add(btnReset); } protectedvoidlogin(ActionEvente)throwsIOException, ClassNotFoundException{ //驗證 //得到GUI界面上的數(shù)據(jù) StringuserName=this.txtLoginUser.getText(); StringserverAddress=this.txtAddress.getText(); intserverPort=Integer.parseInt(this.txtPort.getText()); NormalClass.serverAddress=serverAddress; NormalClass.sererPort=serverPort; //創(chuàng)建一個登錄用戶 StringclientIP=NormalClass.splitIp(InetAddress.getLocalHost() .toString()); intclientPort=NormalClass.randomPort(); loginUser=newUserInfo(userName,null,clientIP,clientPort); loginUser.setImageIndex((int)(Math.random()*10)); //向服務(wù)器建立一個連接:請求 Socketsocket=newSocket(serverAddress,serverPort); //發(fā)送數(shù)據(jù):構(gòu)建一個數(shù)據(jù)包 DataPacketdataPacket=newDataPacket(ICommands.LOGIN,loginUser, null,newDate(),null); OutputStreamout=socket.getOutputStream(); ObjectOutputStreamobjOut=newObjectOutputStream(out); objOut.writeObject(dataPacket); //等待服務(wù)器的響應(yīng) InputStreamin=socket.getInputStream(); ObjectInputStreamobjIn=newObjectInputStream(in); dataPacket=(DataPacket)objIn.readObject(); if(dataPacket.getCommand().equals(ICommands.LOGIN_SUCCESS)){ ClientChatchat=newClientChat(this); chat.setTitle(this.loginUser.getUserName()+"登錄了"); chat.setVisible(true); this.setVisible(false); } objIn.close(); objOut.close(); socket.close(); }}5.3多線程5.3.1服務(wù)端多線程publicServerChatThread(Socketsocket,ServerFrameframe){ this.socket=socket; this.frame=frame; this.start(); } publicvoidrun(){ //接收用戶傳過來的數(shù)據(jù)包 try{ inputStream=this.socket.getInputStream(); objIn=newObjectInputStream(inputStream); DataPacketdataPacket=(DataPacket)this.objIn.readObject(); //用戶要干什么? Stringcommand=dataPacket.getCommand(); if(command.equals(ICommands.LOGIN)){ //表示用戶要登錄 UserInfologinUser=dataPacket.getFromUserInfo(); //身份驗證(略)保存用戶的唯一性 //保存登錄的用戶 this.frame.getAllLoginUser().add(loginUser); //更新用戶的最新信息 this.frame.updateGui(); //發(fā)送一個信息過去 dataPacket.setCommand(ICommands.LOGIN_SUCCESS); dataPacket.setFromUserInfo(null); dataPacket.setToUserInfo(loginUser); this.outPutStream=this.socket.getOutputStream(); this.objOut=newObjectOutputStream(this.outPutStream); this.objOut.writeObject(dataPacket); //向每個登錄的用戶發(fā)送最新的登錄用戶的集合 sendAllUserInfo(); }elseif(command.equals(ICommands.CLOSE_CLIENT_WINDOW)){ //用戶要關(guān)閉了 UserInfounLoginUser=dataPacket.getFromUserInfo(); this.frame.getAllLoginUser().remove(unLoginUser); this.frame.updateGui(); //給客戶 dataPacket.setCommand(ICommands.CLOSE_CLIENT_WINDOW_SUCCESS); this.outPutStream=this.socket.getOutputStream(); this.objOut=newObjectOutputStream(this.outPutStream); this.objOut.writeObject(dataPacket); //把最新的信息告訴客戶 sendAllUserInfo(); } }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(ClassNotFoundExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }finally{ try{ this.objIn.close(); this.socket.close(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } } privatevoidsendAllUserInfo(){ for(inti=0;i<this.frame.getAllLoginUser().size();i++){ UserInfouser=this.frame.getAllLoginUser().get(i); OutputStreamout=null; ObjectOutputStreamobjO=null; //和每個用戶都建立連接 try{ Socketsocket=newSocket(user.getClientAddress(),user .getClientPort()); DataPacketdataPacket=newDataPacket(ICommands.USER_LIST, null,user,newDate(),this.frame.getAllLoginUser()); out=socket.getOutputStream(); objO=newObjectOutputStream(out); objO.writeObject(dataPacket); }catch(UnknownHostExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }finally{ try{ objO.close(); socket.close(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } } }}5.3.2客戶端多線程publicclassClientListerenThreadextendsThread{ privateServerSocketservrSocket; privateClientChatframe; publicClientListerenThread(ServerSocketservrSocket,ClientChatframe){ this.servrSocket=servrSocket; this.frame=frame; this.start(); } publicvoidrun(){ while(true){ try{ Socketsocket=this.servrSocket.accept(); ClientChatThreadchat=newClientChatThread(this.frame,socket); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } }6.運行與測試6.1用戶登錄界面6.2輸入端口界面聊天的雙方必須要有統(tǒng)一的端口號。6.3服務(wù)器記錄,在線的用戶信息。6.4私聊6.4.1登錄6.4.2用戶給指定的好友發(fā)送信息。(私聊)6.4.3指定好友接受到好友信息。(私聊的信息)6.4.5好友回復(fù)我的信息6.5群聊6.5.1發(fā)送群消息6.5.2好友響應(yīng)并接受群聊信息小結(jié)從接觸到計算機我就對網(wǎng)絡(luò)比較感興趣,然后今年又主修了計算機網(wǎng)絡(luò),所以在這次選題的時候我就毫不猶豫選擇了基于socket的網(wǎng)絡(luò)聊天系統(tǒng)。很榮幸的是這此課程設(shè)計我們是以我們的寢室為小組,個人認為這樣的分組有利于交流,和分工以及彼此互相監(jiān)督。我們的分工明確,小組成員彭蛟龍由于在尚學堂機構(gòu)參加培訓,編程能力比較扎實,所以主要負責編碼工作(尤其是難點:服務(wù)器的配置);小組成員陳亞雄愛好PS和視頻制作,負責程序頁面前端的設(shè)計,頁面的優(yōu)化以及文檔的制作;小組成員周小慶擅長管理和愛好鉆研算法,主要負責服務(wù)器客戶端的編寫,整個程序設(shè)計的工作流程管理尤其是他提出采用加密解密來提高傳輸?shù)目煽啃?,是本次課程設(shè)計的亮點也是難點之一;我在本次課程中我主要擔任系統(tǒng)分析的任務(wù),由于曾經(jīng)備考過系分考試,所以這次也是自己理論聯(lián)系實際的一個鍛煉機會。由于這此我們分工明確所以自我感覺彼此的任務(wù)量都不是很大。由于時間比較緊還有一些技術(shù)掌握的不是很好,所以系統(tǒng)需求分析提相互的一些功能沒有完全實現(xiàn),但是最基礎(chǔ)的功能,私聊和群聊都有很好的實現(xiàn)。這次課程設(shè)計我們犯了一些以往的編程經(jīng)常犯的弊端,剛開始對于需求分析不是很在乎,上來就編寫代碼,在老師的提醒下,我們提高了對需求分析重要性的認識,在經(jīng)過一起討論后對于需求分析明確后,運用了UML建模技術(shù)用RationalRose對系統(tǒng)進行了用例建模,靜態(tài)建模(主要有類圖),動態(tài)建模(主要包括序列圖和協(xié)作圖)。對模塊進行了劃分。對程序以后的擴展和一些非功能性需求進行了討論和探討。JAVA網(wǎng)絡(luò)編程課程設(shè)計,讓我有很多的收獲與體會。在整個課程設(shè)計的過程中,我對JAVA網(wǎng)絡(luò)編程的相關(guān)知識有了進一步的了解和掌握。我對軟件開發(fā)有了更深刻的認識,認識到了建模和需求分析的重要性,軟件開發(fā)最重要的不是編碼。在完成設(shè)計的過程中,我查閱了不少資料,提高了自己動手的能力以及解決問題的能力,也增加了寢室之間舍友的關(guān)系。8.參考文獻Java編程思想(ThinkinginJava)原書第四版BrunceEckle著計算機網(wǎng)絡(luò)(第五版)謝希仁著Java核心技術(shù)(卷1:基礎(chǔ)知識)原書第八版CayS.HOratmanGaryCornell著Java核心技術(shù)(卷1:高級特性)原書第八版CayS.HOratmanGaryCornell著軟件工程導論(第五版)張海潘著附錄資料:不需要的可以自行刪除busybox詳解制作根文件系統(tǒng)詳解制作根文件系統(tǒng)一、FHS(FilesystemHierarchyStandard)標準介紹當我們在linux下輸入ls

/的時候,見到的目錄結(jié)構(gòu)以及這些目錄下的內(nèi)容都大同小異,這是因為所有的linux發(fā)行版在對根文件系統(tǒng)布局上都遵循FHS標準的建議規(guī)定。該標準規(guī)定了根目錄下各個子目錄的名稱及其存放的內(nèi)容:目錄名存放的內(nèi)容/bin必備的用戶命令,例如ls、cp等/sbin必備的系統(tǒng)管理員命令,例如ifconfig、reboot等/dev設(shè)備文件,例如mtdblock0、tty1等/etc系統(tǒng)配置文件,包括啟動文件,例如inittab等/lib必要的鏈接庫,例如C鏈接庫、內(nèi)核模塊/home普通用戶主目錄/rootroot用戶主目錄/usr/bin非必備的用戶程序,例如find、du等/usr/sbin非必備的管理員程序,例如chroot、inetd等/usr/lib庫文件/var守護程序和工具程序所存放的可變,例如日志文件/proc用來提供內(nèi)核與進程信息的虛擬文件系統(tǒng),由內(nèi)核自動生成目錄下的內(nèi)容/sys用來提供內(nèi)核與設(shè)備信息的虛擬文件系統(tǒng),由內(nèi)核自動生成目錄下的內(nèi)容/mnt文件系統(tǒng)掛接點,用于臨時安裝文件系統(tǒng)/tmp臨時性的文件,重啟后將自動清除

制作根文件系統(tǒng)就是要建立以上的目錄,并在其中建立完整目錄內(nèi)容。其過程大體包括:編譯/安裝busybox,生成/bin、/sbin、/usr/bin、/usr/sbin目錄利用交叉編譯工具鏈,構(gòu)建/lib目錄手工構(gòu)建/etc目錄手工構(gòu)建最簡化的/dev目錄創(chuàng)建其它空目錄配置系統(tǒng)自動生成/proc目錄利用udev構(gòu)建完整的/dev目錄制作根文件系統(tǒng)的jffs2映像文件下面就來詳細介紹這個過程。二、編譯/安裝busybox,生成/bin、/sbin、/usr/bin、/usr/sbin目錄這些目錄下存儲的主要是常用命令的二進制文件。如果要自己編寫這幾百個常用命令的源程序,mygod,這簡直是一個噩夢!好在我們有嵌入式Linux系統(tǒng)的瑞士軍刀——busybox,事情就簡單很多。1、從/下載busybox-1.7.0.tar.bz22、tarxjvfbusybox-1.7.0.tar.bz2解包3、修改Makefile文件175ARCH

?=arm

176CROSS_COMPILE

?=arm-linux-4、makemenuconfig配置busyboxbusybox配置主要分兩部分。第一部分是BusyboxSettings,主要編譯和安裝busybox的一些選項。這里主要需要配置:1)、BuildOptions--BuildBusyBoxasastaticbinary(nosharedlibs),表示編譯busybox時,是否靜態(tài)鏈接C庫。我們選擇動態(tài)鏈接C庫。2)、InstallationOptions--Appletslinks(assoft-links)--(X)assoft-links,表示安裝busybox時,將各個命令安裝為指向busybox的軟鏈接還是硬鏈接。我們選擇軟鏈接。3)、InstallationOptions--(/work/nfs_root/fs_mini3)BusyBoxinstallationprefix,表示busybox的安裝位置。我們選擇/work/nfs_root/fs_mini34)BusyboxLibraryTuning。保留Commandlineediting以支持命令行編輯;保留Historysize以支持記憶歷史命令;選中Tabcompletion和Usernamecompletion以支持命令自動補全第二部分是Applets,他將busybox的支持的幾百個命令分門別類。我們只要在各個門類下選擇想要的命令即可。這里我們基本保持默認設(shè)置。1)選中NetworkingUtilities--httpd下的Enable-u<user>option,以啟用http服務(wù)器的功能allowstheservertorunasaspecificuser5、編譯busyboxmake6、安裝busyboxmakeinstall安裝完成后,可以看到在/work/nfs_root/fs_mini3目錄下生成了binsbinusr/binusr/sbin目錄,其下包含了我們常用的命令,這些命令都是指向bin/busybox的軟鏈接,而busybox本身的大小不到800K:dennis@dennis-desktop:/work/nfs_root/fs_mini3$ls

bin

linuxrc

sbin

usr

dennis@dennis-desktop:/work/nfs_root/fs_mini3$

ls-lbin

total740

lrwxrwxrwx1dennisdennis

72010-04-0323:57addgroup->busybox

lrwxrwxrwx1dennisdennis

72010-04-0323:57adduser->busybox

lrwxrwxrwx1dennisdennis

72010-04-0323:57ash->busybox

-rwxr-xr-x1dennisdennis7496322010-04-0323:57busybox

lrwxrwxrwx1dennisdennis

72010-04-0323:57cat–>busybox而普通PC機上的ls命令就有差不多80K的大?。篸ennis@dennis-desktop:/work/nfs_root/fs_mini3$ls-l/bin/ls

-rwxr-xr-x1rootroot780042007-09-2920:51/bin/lsbusybox以它嬌小的身軀容納了數(shù)以百計的命令代碼,實在是讓人佩服不已,其不愧嵌入式系統(tǒng)瑞士軍刀之美譽。據(jù)說,busybox的作者身患絕癥,這更讓人欽佩GNU開源軟件的作者們。三、利用交叉編譯工具鏈,構(gòu)建/lib目錄光有應(yīng)用程序(命令)是不夠的,因為應(yīng)用程序本身需要使用C庫的庫函數(shù),因此還必需制作forARM的C庫,并將其放置于/lib目錄。mygod,要自己寫C庫的源代碼嗎?不用!還記得交叉編譯工具鏈的3個組成部分嗎?交叉編譯器、forARM的C庫和二進制工具。哈哈,forARM的C庫是現(xiàn)成的,我們只需要拷貝過來就可以了。遺憾的是:整個C庫目錄下的文件總大小有26M。而我們根文件系統(tǒng)所在分區(qū)不過區(qū)區(qū)16M而已,根本放不下。怎么辦呢?dennis@dennis-desktop:/work/nfs_root/fs_mini3$du-s--si/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib

26M

/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib需要C庫目錄下所有的文件嗎?no,absolutelyno!讓我們來分析一下glibc庫目錄下內(nèi)容的組成。該目錄下的子目錄和文件共分8類:目標文件,如crtn.o,用于gcc鏈接可執(zhí)行文件libtool庫文件(.la),在鏈接庫文件時這些文件會被用到,比如他們列出了當前庫文件所依賴的其它庫文件,程序運行時無需這些文件gconv目錄,里面是各種鏈接腳本,在編譯應(yīng)用程序時,他們用于指定程序的運行地址,各段的位置等靜態(tài)庫文件(.a),例如libm.a,libc.a動態(tài)庫文件(.so、.so.[0-9]*)動態(tài)鏈接庫加載器ld-2.3.6.so、ld-linux.so.2其它目錄及文件很顯然,第1、2、3、4、7類文件和目錄是不需要拷貝的。由于動態(tài)鏈接的應(yīng)用程序本身并不含有它所調(diào)用的C庫函數(shù)的代碼,因此執(zhí)行時需要動態(tài)鏈接庫加載器來為它加載相應(yīng)的C庫文件,所以第6類文件是需要拷貝的。除此之外,第5類文件當然要拷貝。但第5類文件的大小也相當大。dennis@dennis-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$du-c--si*.so*7.2M

total需要全部拷貝嗎?非也,非也!其實,需要哪些庫完全取決于要運行的應(yīng)用程序使用了哪些庫函數(shù)。如果我們只制作最簡單的系統(tǒng),那么我們只需要運行busybox這一個應(yīng)用程序即可。通過執(zhí)行dennis@dennis-desktop:/work/nfs_root/fs_mini3$arm-linux-readelf-abin/busybox|grep'Shared'

0x00000001(NEEDED)

Sharedlibrary:[libcrypt.so.1]

0x00000001(NEEDED)

Sharedlibrary:[libm.so.6]

0x00000001(NEEDED)

Sharedlibrary:[libc.so.6]可知:busybox只用到了3個庫:通用C庫(libc)、數(shù)學庫(libm)、加密庫(libcrypt),因此我們只需要拷貝這3個庫的庫文件即可。但是每個庫都有4個文件,4個文件都要拷貝嗎?當然不是。dennis@dennis-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$ls-llibcrypt[.-]*

-rwxr-xr-x1dennisdennis307002008-01-2205:32libcrypt-2.3.6.so

-rw-r--r--1dennisdennis231182008-01-2205:32libcrypt.a

lrwxrwxrwx1dennisdennis

132008-12-2215:38libcrypt.so->libcrypt.so.1

lrwxrwxrwx1dennisdennis

172008-12-2215:38libcrypt.so.1->libcrypt-2.3.6.so

dennis@dennis-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$ls-llibm[.-]*

-rwxr-xr-x1dennisdennis

7790962008-01-2205:31libm-2.3.6.so

-rw-r--r--1dennisdennis11342822008-01-2205:32libm.a

lrwxrwxrwx1dennisdennis

92008-12-2215:38libm.so->libm.so.6

lrwxrwxrwx1dennisdennis

132008-12-2215:38libm.so.6->libm-2.3.6.so

dennis@dennis-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$ls-llibc[.-]*

-rwxr-xr-x1dennisdenni01-2205:48libc-2.3.6.so

-rw-r--r--1dennisdennis27682802008-01-2205:31libc.a

-rw-r--r--1dennisdennis

1952008-01-2205:34libc.so

lrwxrwxrwx1dennisdennis

132008-12-2215:38libc.so.6->libc-2.3.6.so4個文件中的.a文件是靜態(tài)庫文件,是不需要拷貝的。另外3個文件是:實際的共享鏈接庫:libLIBRARY_NAME-GLIBC_VERSION.so。當然需要拷貝。主修訂版本的符號鏈接,指向?qū)嶋H的共享鏈接庫:libLIBRARY_NAME.so.MAJOR_REVISION_VERSION,程序一旦鏈接了特定的鏈接庫,將會參用該符號鏈接。程序啟動時,加載器在加載程序前,會檢索該文件。所以需要拷貝。與版本無關(guān)的符號鏈接,指向主修訂版本的符號連接(libc.so是唯一的例外,他是一個鏈接命令行:libLIBRARY_NAME.so,是為編譯程序時提供一個通用條目)。這些文件在程序被編譯時會被用到,但在程序運行時不會被用到,所以不必拷貝它。關(guān)于共享庫的2個符號鏈接的作用的特別說明:當我們使用gcc

hello.c

-o

hello

-lm編譯程序時,gcc會根據(jù)-lm的指示,加頭(lib)添尾(.so)得到libm.so,從而沿著與版本無關(guān)的符號鏈接(libm.so->libm.so.6)找到libm.so.6并記錄在案(hello的ELF頭中),表示hello需要使用libm.so.6這個庫文件所代表的數(shù)學庫中的庫函數(shù)。而當hello被執(zhí)行的時候,動態(tài)鏈接庫加載器會從hello的ELF頭中找到libm.so.6這個記錄,然后沿著主修訂版本的符號鏈接(libm.so.6->libm-2.3.6.so)找到實際的共享鏈接庫libm-2.3.6.so,從而將其與hello作動態(tài)鏈接。可見,與版本無關(guān)的符號鏈接是供編譯器使用的,主修訂版本的符號鏈接是供動態(tài)鏈接庫加載器使用的,而實際的共享鏈接庫則是供應(yīng)用程序使用的。通過以上分析,我們只需要拷貝3個庫(每個庫各1個主修訂版本的符號鏈接和1個實際的共享鏈接庫)以及動態(tài)鏈接庫加載器(1個符號鏈接和1個實體文件)。步驟如下:dennis@dennis-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$mkdir/work/nfs_root/fs_mini3/libdennis@dennis-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$cp

libcrypt-*/work/nfs_root/fs_mini3/lib

dennis@dennis-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$cp-llibcrypt.so.*/work/nfs_root/fs_mini3/lib

dennis@dennis-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$cp

libm-*/work/nfs_root/fs_mini3/lib

dennis@dennis-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$cp-llibm.so.*/work/nfs_root/fs_mini3/lib

dennis@dennis-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$cp

libc-*/work/nfs_root/fs_mini3/lib

dennis@dennis-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$cp-llibc.so.*/work/nfs_root/fs_mini3/libdennis@dennis-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$cp-lld-*/work/nfs_root/fs_mini3/lib四、手工構(gòu)建/etc目錄/etc目錄存放的是系統(tǒng)程序的主配置文件,因此需要哪些配置文件取決于要運行哪些系統(tǒng)程序。即使最小的系統(tǒng)也一定會運行1號用戶進程init,所以我們至少要手工編寫init的主配置文件inittab。busybox的inittab文件的語法、語義與傳統(tǒng)的SYSV的inittab有所不同。inittab文件中每個條目用來定義一個需要init啟動的子進程,并確定它的啟動方式,格式為<id>:<runlevel>:<action>:<process>。例如:ttySAC0::askfirst:-/bin/sh<id>表示子進程要使用的控制臺,若省略則使用與init進程一樣的控制臺<runlevel>表示運行級別,busyboxinit程序這個字段沒有意義<action>表示init進程如何控制這個子進程sysinit:系統(tǒng)啟動后最先執(zhí)行,只執(zhí)行一次,init進程等待它結(jié)束后才繼續(xù)執(zhí)行其它動作wait:系統(tǒng)執(zhí)行完sysinit條目后執(zhí)行,只執(zhí)行一次,init進程等待它結(jié)束后才繼續(xù)執(zhí)行其它動作once:系統(tǒng)執(zhí)行完wait條目后執(zhí)行,只執(zhí)行一次,init進程不等待它結(jié)束respawn:啟動完once進程后,init進程監(jiān)測發(fā)現(xiàn)子進程退出時,重新啟動它askfirst:啟動完respawn進程后,與respawn類似,不過init進程先輸出”PleasepressEntertoactivatethisconsole“,等用戶輸入回車后才啟動子進程shutdown:當系統(tǒng)關(guān)機時restart:B

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論