2023年全國碩士研究生考試考研英語一試題真題(含答案詳解+作文范文)_第1頁
已閱讀1頁,還剩39頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、<p>  linux TCP服務(wù)器/客戶端通信程序</p><p>  摘要:隨著計算機(jī)網(wǎng)絡(luò)的不斷發(fā)展,網(wǎng)絡(luò)編程變得越來越重要,除了簡單的WEB編程外,還包括利用套接字(Socket)進(jìn)行客戶/服務(wù)器應(yīng)用程序的設(shè)計。本文先對與套接字相關(guān)的概念和函數(shù)作了一般性介紹,并提出多線程的編程方法和設(shè)計流程,也就具體的工程實(shí)例進(jìn)行了流程分析。本文中,對計算機(jī)的網(wǎng)絡(luò)模型進(jìn)行了簡要的分析,并對TCP的握手模型進(jìn)行了概

2、述;在多線程編程中,本文詳細(xì)分析了多線程的互斥模型,講解了多種線程之間的同步方法,并在程序設(shè)計中得到體現(xiàn),詳細(xì)講述了Linux中的TCP服務(wù)器/客戶端通信程序,并對結(jié)果進(jìn)行了驗(yàn)證。</p><p>  關(guān)鍵字:網(wǎng)絡(luò)編程 ;多線程;套接字</p><p><b>  目 錄</b></p><p><b>  緒論1</b>

3、;</p><p><b>  1. 課程背景1</b></p><p>  2. 選題的目的和意義1</p><p>  3. 國內(nèi)外研究現(xiàn)狀1</p><p>  4. 主要研究內(nèi)容1</p><p>  第1章 需求分析3</p><p>  1.1 設(shè)計目

4、的3</p><p>  1.2 課題要求3</p><p>  1.3 任務(wù)分析3</p><p>  第2章 環(huán)境搭建4</p><p>  2.1 Ubuntu系統(tǒng)安裝4</p><p>  2.2 開發(fā)環(huán)境搭建7</p><p>  2.2.1 NFS環(huán)境介紹7</p

5、><p>  2.2.2 NFS安裝7</p><p>  2.2.3 掛載NFS文件系統(tǒng)7</p><p>  2.2.4 交叉工具安裝8</p><p>  第3章 軟件設(shè)計9</p><p>  3.1 TCP/IP協(xié)議9</p><p>  3.1.1 網(wǎng)絡(luò)模型9</p&g

6、t;<p>  3.1.2 TCP連接9</p><p>  3.2 多線程編程10</p><p>  3.3 Socket網(wǎng)絡(luò)編程模型12</p><p>  3.3.1 TCP Server編程模型12</p><p>  3.3.2 TCP Client編程模型13</p><p>  

7、3.4 程序設(shè)計13</p><p>  3.4.1 主要內(nèi)容13</p><p>  3.4.2 服務(wù)器端程序設(shè)計14</p><p>  3.4.3 客戶端程序設(shè)計16</p><p>  第4章 綜合測試18</p><p>  4.1 功能測試18</p><p><b

8、>  第5章 結(jié)論20</b></p><p><b>  參考文獻(xiàn)21</b></p><p>  附錄一 服務(wù)器端程序22</p><p>  附錄二 客戶端程序32</p><p><b>  緒論</b></p><p>  Linux經(jīng)歷了

9、20多年的發(fā)展,已經(jīng)成為了一個功能強(qiáng)大而穩(wěn)定的操作系統(tǒng),在嵌入式系統(tǒng)中也得到廣泛的運(yùn)用,伴隨著物聯(lián)網(wǎng)技術(shù)的普及,網(wǎng)絡(luò)通信在嵌入式系統(tǒng)中扮演著舉足輕重的作用。</p><p><b>  課程背景</b></p><p>  隨著時代的發(fā)展,網(wǎng)絡(luò)通信在我們的生活中愈來愈重要,在互聯(lián)網(wǎng)技術(shù)基礎(chǔ)上延伸和擴(kuò)展來的物聯(lián)網(wǎng)技術(shù),正逐漸改變著我們的世界?;ヂ?lián)網(wǎng)在現(xiàn)實(shí)生活中的應(yīng)用很廣

10、泛,互聯(lián)網(wǎng)給我們的現(xiàn)實(shí)生活帶來了很大的方便;互聯(lián)網(wǎng)是全球性的,這也就意味著我們能夠打破時空的界限,通過互聯(lián)網(wǎng)接觸到世界的每一個角落;因?yàn)榛ヂ?lián)網(wǎng)的強(qiáng)大力量,這個時代的文明發(fā)展得到極大地提高。</p><p><b>  選題的目的和意義</b></p><p>  由于互聯(lián)網(wǎng)超乎尋常的強(qiáng)大力量,改變了這個時代的交流方式,改變著人們的生活,未來,我們還將在互聯(lián)網(wǎng)領(lǐng)域得到更

11、多的進(jìn)步,會影響生活中的方方面面。</p><p><b>  國內(nèi)外研究現(xiàn)狀</b></p><p>  互聯(lián)網(wǎng)從誕生至今,讓人類文明得到巨大的推動,伴隨著互聯(lián)網(wǎng)的發(fā)展,各種依托互聯(lián)網(wǎng)的技術(shù)得到迅速發(fā)展,Linux操作系統(tǒng)依據(jù)其優(yōu)良的性能和網(wǎng)絡(luò)功能,在各個領(lǐng)域都得到極大的普及。21世紀(jì),是互聯(lián)網(wǎng)發(fā)展的有一個階段,我們國家已經(jīng)將互聯(lián)網(wǎng)的發(fā)展提升到了戰(zhàn)略高度,明確表示要

12、建成互聯(lián)網(wǎng)強(qiáng)國,我國到目前為止,已經(jīng)誕生了一大批優(yōu)秀的互聯(lián)網(wǎng)企業(yè),全世界都將在互聯(lián)網(wǎng)的推動下,進(jìn)入一個全新的時代。</p><p><b>  主要研究內(nèi)容</b></p><p>  設(shè)計TCP服務(wù)器程序,使用多線程實(shí)現(xiàn)”生產(chǎn)者-消費(fèi)者“模型,建立TCP服務(wù)器,響應(yīng)客戶端請求,發(fā)送客戶端指定的請求數(shù)據(jù)。</p><p><b>  

13、主要包括以下內(nèi)容:</b></p><p>  創(chuàng)建線程持續(xù)產(chǎn)生數(shù)據(jù),數(shù)據(jù)包含(學(xué)號,姓名(拼音),年齡,身高,體重,當(dāng)前系統(tǒng)時間(納秒數(shù))使用gettimeofday(),可使用隊(duì)列/多維數(shù)組存儲數(shù)據(jù);</p><p>  創(chuàng)建TCP服務(wù)器線程,響應(yīng)多個客戶端的連接,讀取隊(duì)列/數(shù)組,向客戶端發(fā)送指定“學(xué)號”的數(shù)據(jù)。設(shè)計TCP服務(wù)器程序;</p><p>

14、;  創(chuàng)建TCP客戶端接收線程,連接服務(wù)器并請求指定“學(xué)號”的數(shù)據(jù),接收數(shù)據(jù)并存儲在文件中。要求存儲有意義的數(shù)據(jù),由于TCP是基于字節(jié)流的特征,需要做組包處理;</p><p><b>  需求分析</b></p><p><b>  設(shè)計目的</b></p><p>  通過對專業(yè)知識的熟練運(yùn)用,理解Linux網(wǎng)絡(luò)編程的

15、流程,了解互聯(lián)網(wǎng)的基本架構(gòu),熟悉多線程編程的思想。同時,通過本課程設(shè)計,可以培養(yǎng)以下能力:</p><p>  獨(dú)立工作能力與創(chuàng)造力;</p><p>  綜合運(yùn)用專業(yè)及基礎(chǔ)知識的能力;</p><p>  解決實(shí)際工程技術(shù)問題的能力;</p><p>  查閱圖書資料、產(chǎn)品手冊和各種工具書的能力;</p><p> 

16、 書寫技術(shù)報告和編制技術(shù)資料的能力。</p><p><b>  課題要求</b></p><p>  使用多線程實(shí)現(xiàn)”生產(chǎn)者-消費(fèi)者“模型,建立TCP服務(wù)器,響應(yīng)客戶端請求,發(fā)送客戶端指定的請求數(shù)據(jù)。</p><p><b>  任務(wù)分析</b></p><p>  創(chuàng)建線程持續(xù)產(chǎn)生數(shù)據(jù),數(shù)據(jù)包含

17、(學(xué)號,姓名(拼音),年齡,身高,體重,當(dāng)前系統(tǒng)時間(納秒數(shù))使用gettimeofday),可使用隊(duì)列/多維數(shù)組存儲數(shù)據(jù)。理解常用的數(shù)據(jù)結(jié)構(gòu),熟練掌握C編程語言。</p><p>  創(chuàng)建TCP服務(wù)器線程,響應(yīng)多個客戶端的連接,讀取隊(duì)列/數(shù)組,向客戶端發(fā)送指定“學(xué)號”的數(shù)據(jù),設(shè)計TCP服務(wù)器程序,掌握網(wǎng)絡(luò)編程中服務(wù)器端的編程流程。</p><p>  創(chuàng)建TCP客戶端接收線程,連接服務(wù)器

18、并請求指定“學(xué)號”的數(shù)據(jù),接收數(shù)據(jù)并存儲在文件中。要求存儲有意義的數(shù)據(jù),由于TCP是基于字節(jié)流的特征,需要做組包處理。掌握網(wǎng)絡(luò)編程中客戶端的編程流程。</p><p>  最終的目的是熟練掌握網(wǎng)絡(luò)編程的編程方法,理解常用的數(shù)據(jù)結(jié)構(gòu)的基本思想,掌握編程語言,理解多線程編程在實(shí)際工程中的應(yīng)用。</p><p><b>  環(huán)境搭建</b></p><p

19、>  Ubuntu系統(tǒng)安裝</p><p>  考慮到Windows系統(tǒng)的普及程度,本課程實(shí)際將利用虛擬機(jī)來進(jìn)行開發(fā),首先我們需要搭建虛擬機(jī)開發(fā)環(huán)境。</p><p><b>  創(chuàng)建虛擬機(jī)</b></p><p><b>  圖2.1.1</b></p><p><b>  選擇操

20、作系統(tǒng)</b></p><p><b>  圖2.1.2</b></p><p>  3.配置處理器和內(nèi)存</p><p><b>  圖2.1.3</b></p><p><b>  圖2.1.4</b></p><p><b>

21、  安裝系統(tǒng)</b></p><p><b>  圖2.1.5</b></p><p><b>  安裝成功界面</b></p><p><b>  圖2.1.6</b></p><p><b>  開發(fā)環(huán)境搭建</b></p>

22、<p><b>  NFS環(huán)境介紹</b></p><p>  NFS(Network File System)即網(wǎng)絡(luò)文件系統(tǒng),是FreeBSD支持的文件系統(tǒng)中的一種,它允許網(wǎng)絡(luò)中的計算機(jī)之間通過TCP/IP網(wǎng)絡(luò)共享資源。在NFS的應(yīng)用中,本地NFS的客戶端應(yīng)用可以透明地讀寫位于遠(yuǎn)端NFS服務(wù)器上的文件,就像訪問本地文件一樣。</p><p><b&g

23、t;  NFS安裝</b></p><p>  1.NFS是網(wǎng)絡(luò)文件系統(tǒng)系統(tǒng)的縮寫,可以用于Linux和Linux之間傳遞文件,實(shí)現(xiàn)數(shù)據(jù)共享。安裝命令如下:</p><p>  apt-get install nfs-kernel-server</p><p><b>  2.修改配置文件</b></p><p&

24、gt;  打開/etc/exports文件,增加mount -t nfs/NFS (rw,sync,no_root_squash,no_subtree_check)</p><p>  開發(fā)板和其他 Linux 主機(jī)可以通過網(wǎng)絡(luò)訪問/NFS 目錄。</p><p><b>  3.啟動NFS</b></p><p>  sudo service

25、 rpcbind start </p><p>  sudo service nfs-kernel-server start</p><p><b>  掛載NFS文件系統(tǒng)</b></p><p>  mount -t nfs -o intr,nolock,rsize=1024,wsize=1024 192.168.1.86:/opt/ /mn

26、t</p><p><b>  交叉工具安裝</b></p><p>  1.在/usr/local/下建立交叉編譯器的安裝目錄arm:</p><p>  sudo  mkdir /usr/local/arm</p><p>  2.將下載的交叉編譯器包解壓到/usr/local/arm目錄下:</p&

27、gt;<p>  sudo tar jxvf cross-4.2.2-eabi.tar.bz2 -C /usr/local/arm/ </p><p>  3.解壓成功后,修改PATH環(huán)境變量:</p><p>  sudo vim  /etc/profile</p><p>  在文件為加入交叉編譯器arm-linux-所在的路徑

28、:</p><p>  export PATH=$PATH:/usr/local/arm/4.2.2-eabi/usr/bin</p><p>  4.更新一下配置文件/etc/profile:</p><p>  source /etc/profile</p><p><b>  軟件設(shè)計</b></p>

29、<p><b>  TCP/IP協(xié)議</b></p><p><b>  網(wǎng)絡(luò)模型</b></p><p>  圖 3-1-1 網(wǎng)絡(luò)模型</p><p>  如圖3-1-1所示,在TCP/IP協(xié)議中,將互聯(lián)網(wǎng)劃分成為應(yīng)用層、傳輸層、網(wǎng)絡(luò)層、網(wǎng)絡(luò)接口層,其中網(wǎng)絡(luò)接口層的主要功能是提供二進(jìn)制傳輸和介質(zhì)訪問的功能;網(wǎng)

30、絡(luò)層負(fù)責(zé)IP尋址和路由,其中要考慮路由算法,擁塞控制等問題;傳輸層負(fù)責(zé)應(yīng)用程序之間的連接;</p><p><b>  TCP連接</b></p><p>  TCP IP一般通過internet串行線路協(xié)議SLIP或點(diǎn)對點(diǎn)協(xié)議PPP在串行線上進(jìn)行數(shù)據(jù)傳送。TCP/IP協(xié)議的基本傳輸單位是數(shù)據(jù)包 (datagram)。TCP協(xié)議負(fù)責(zé)把數(shù)據(jù)分成若干個數(shù)據(jù)包/段,并給每個

31、數(shù)據(jù)包加上包頭,IP協(xié)議在每個包頭上再加上接收端主機(jī)地址,這樣數(shù)據(jù)找到自己要去的地方。如果傳輸過程中出現(xiàn)數(shù)據(jù)丟失、數(shù)據(jù)失真等情況,TCP協(xié)議會自動要求數(shù)據(jù)重新傳輸并重新組包。TCP協(xié)議保證數(shù)據(jù)傳輸?shù)馁|(zhì)量,IP協(xié)議保證數(shù)據(jù)的傳輸。數(shù)據(jù)在傳輸時每通過一層就要在數(shù)據(jù)上加個包頭,其中數(shù)據(jù)供接收端同一層協(xié)議使用,而在接收端每經(jīng)過一層要把用過的包頭去掉,這樣來保證傳輸數(shù)據(jù)的格式完全一致。TCP/IP協(xié)議需要針對不同的網(wǎng)絡(luò)進(jìn)行不同的設(shè)置,且每個節(jié)點(diǎn)一

32、般需要一個“IP地址”、一個“子網(wǎng)掩碼”、一個“默認(rèn)網(wǎng)關(guān)”。不過可以通過動態(tài)主機(jī)配置協(xié)議(DHCP),給客戶端自動分配一個IP地址,這樣避免了出錯也簡化了TCP/IP協(xié)議的設(shè)置。</p><p>  如圖3-1-2所示,TCP是通過3次握手建立的:</p><p>  客戶端給服務(wù)器發(fā)送SYN(syn = j)包,進(jìn)入SYN_SEND狀態(tài)。</p><p>  服務(wù)

33、器接收到SYNC包,確認(rèn)客戶的SYN(ack = j+1),同時自己也發(fā)送一個SYN包(syn = k),把它倆都發(fā)送出去,服務(wù)器進(jìn)入SYN_SEND狀態(tài)。</p><p>  客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送ACK(ack = k+1),客戶端和服務(wù)器都進(jìn)入ESTABLISHED狀態(tài)。此時,連接已經(jīng)建立完畢,可以相互發(fā)送發(fā)送消息。</p><p>  圖 3-1-2 三次

34、握手示意圖</p><p><b>  多線程編程</b></p><p>  進(jìn)程是系統(tǒng)中程序執(zhí)行和資源分配的基本單位。每個進(jìn)程都擁有自己的數(shù)據(jù)段、代碼段和堆棧段,這就造成了進(jìn)程在進(jìn)行切換等操作時都需要有比較復(fù)雜的上下文切換等動作。為了進(jìn)一步減少處理機(jī)的空轉(zhuǎn)時間,支持多處理器以及減少上下文切換開銷,進(jìn)程在演化中出現(xiàn)了另一個概念——線程。它是進(jìn)程內(nèi)獨(dú)立的一條運(yùn)行路線,

35、處理器調(diào)度的最小單元,也可以稱為輕量級進(jìn)程。線程可以對進(jìn)程的內(nèi)存空間和資源進(jìn)行訪問,并與同一進(jìn)程中的其他線程共享。因此,線程的上下文切換的開銷比創(chuàng)建進(jìn)程小很多。</p><p>  同進(jìn)程一樣,線程也將相關(guān)的執(zhí)行狀態(tài)和存儲變量放在線程控制表內(nèi)。一個進(jìn)程可以有多個線程,也就是有多個線程控制表及堆棧寄存器,但卻共享一個用戶地址空間。要注意的是,由于線程共享了進(jìn)程的資源和地址空間,因此,任何線程對系統(tǒng)資源的操作都會給其

36、他線程帶來影響。由此可知,多線程中的同步是非常重要的問題,以下是線程同步用到的一些方法:</p><p><b>  互斥鎖</b></p><p>  互斥鎖是用一種簡單的加鎖方法來控制對共享資源的原子操作。這個互斥鎖只有兩種狀態(tài),也就是上鎖和解鎖,可以把互斥鎖看作某種意義上的全局變量。在同一時刻只能有一個線程掌握某個互斥鎖,擁有上鎖狀態(tài)的線程能夠?qū)蚕碣Y源進(jìn)行操作

37、。若其他線程希望上鎖一個已經(jīng)被上鎖的互斥鎖,則該線程就會掛起,直到上鎖的線程釋放掉互斥鎖為止??梢哉f,這把互斥鎖保證讓每個線程對共享資源按順序進(jìn)行原子操作。</p><p>  互斥鎖可以分為快速互斥鎖、遞歸互斥鎖和檢錯互斥鎖。這三種鎖的區(qū)別主要在于其他未占有互斥鎖的線程在希望得到互斥鎖時是否需要阻塞等待??焖冁i是指調(diào)用線程會阻塞直至擁有互斥鎖的線程解鎖為止。遞歸互斥鎖能夠成功地返回,并且增加調(diào)用線程在互斥上加鎖

38、的次數(shù),而檢錯互斥鎖則為快速互斥鎖的非阻塞版本,它會立即返回并返回一個錯誤信息。</p><p>  互斥鎖機(jī)制主要包括下面的基本函數(shù):</p><p>  互斥鎖初始化:pthread_mutex_init()</p><p>  互斥鎖上鎖:pthread_mutex_lock()</p><p>  互斥鎖判斷上鎖:pthread_mu

39、tex_trylock()</p><p>  互斥鎖解鎖:pthread_mutex_unlock()</p><p>  消除互斥鎖:pthread_mutex_destroy()</p><p><b>  信號量</b></p><p>  信號量也就是操作系統(tǒng)中所用到的PV原子操作,它廣泛用于進(jìn)程或線程間的同步

40、與互斥。信號量本質(zhì)上是一個非負(fù)的整數(shù)計數(shù)器,它被用來控制對公共資源的訪問。</p><p>  PV原子操作是對整數(shù)計數(shù)器信號量sem的操作。一次P操作使sem減一,而一次V操作使sem加一。進(jìn)程(或線程)根據(jù)信號量的值來判斷是否對公共資源具有訪問權(quán)限。當(dāng)信號量sem的值大于等于零時,該進(jìn)程(或線程)具有公共資源的訪問權(quán)限;相反,當(dāng)信號量sem的值小于零時,該進(jìn)程(或線程)就將阻塞直到信號量sem的值大于等于0為

41、止。</p><p>  信號量機(jī)制主要包括下面的基本函數(shù):</p><p>  創(chuàng)建信號量: sem_init()</p><p>  等待信號量:sem_wait()和sem_trywait()</p><p>  喚醒進(jìn)程:sem_post()</p><p>  獲取信號量: sem_getvalue()<

42、;/p><p>  刪除信號量: sem_destroy()</p><p>  Socket網(wǎng)絡(luò)編程模型</p><p>  在Linux中的網(wǎng)絡(luò)編程是通過socket接口來進(jìn)行的。socket是一種特殊的I/O接口,它也是一種文件描述符。它是一種常用的進(jìn)程之間通信機(jī)制,通過它不僅能實(shí)現(xiàn)本地機(jī)器上的進(jìn)程之間的通信,而且通過網(wǎng)絡(luò)能夠在不同機(jī)器上的進(jìn)程之間進(jìn)行通信。&l

43、t;/p><p>  源IP地址和目的IP地址以及源端口號和目的端口號的組合稱為套接字。其用于標(biāo)識客戶端請求的服務(wù)器和服務(wù),它是網(wǎng)絡(luò)通信過程中端點(diǎn)的抽象表示,包含進(jìn)行網(wǎng)絡(luò)通信必需的五種信息:連接使用的協(xié)議,本地主機(jī)的IP地址,本地進(jìn)程的協(xié)議端口,遠(yuǎn)地主機(jī)的IP地址,遠(yuǎn)地進(jìn)程的協(xié)議端口。</p><p>  TCP Server編程模型</p><p>  圖 3-2-1

44、 Server編程模型</p><p>  進(jìn)行版本協(xié)商(WSAStartup)</p><p>  創(chuàng)建一個套接字(socket())</p><p>  將套接字設(shè)為監(jiān)聽狀態(tài)(listen())</p><p>  接受客戶端的連接請求(accept())</p><p>  發(fā)送或者接收數(shù)據(jù)(send()/rec

45、v())</p><p>  關(guān)閉套接字(close())</p><p>  TCP Client編程模型</p><p>  圖 3-2-2 Client編程模型</p><p>  進(jìn)行版本協(xié)商(WSAStartup)</p><p>  創(chuàng)建一個套接字(socket())</p><p&g

46、t;  連接到服務(wù)器(connect())</p><p>  發(fā)送或者接收函數(shù)(send()/recv())</p><p>  關(guān)閉套接字(close())</p><p><b>  程序設(shè)計</b></p><p><b>  主要內(nèi)容</b></p><p>  設(shè)

47、計TCP服務(wù)器程序,使用多線程實(shí)現(xiàn)”生產(chǎn)者-消費(fèi)者“模型,建立TCP服務(wù)器,響應(yīng)客戶端請求,發(fā)送客戶端指定的請求數(shù)據(jù)。</p><p>  1.創(chuàng)建線程持續(xù)產(chǎn)生數(shù)據(jù),數(shù)據(jù)包含(學(xué)號,姓名(拼音),年齡,身高,體重,當(dāng)前系統(tǒng)時間(納秒數(shù))使用gettimeofday),可使用隊(duì)列/多維數(shù)組存儲數(shù)據(jù)。</p><p>  2.創(chuàng)建TCP服務(wù)器線程,響應(yīng)多個客戶端的連接,讀取隊(duì)列/數(shù)組,向客戶端

48、發(fā)送指定“學(xué)號”的數(shù)據(jù)。設(shè)計TCP服務(wù)器程序。</p><p>  3.創(chuàng)建TCP客戶端接收線程,連接服務(wù)器并請求指定“學(xué)號”的數(shù)據(jù),接收數(shù)據(jù)并存儲在文件中。要求存儲有意義的數(shù)據(jù),由于TCP是基于字節(jié)流的特征,需要做組包處理</p><p><b>  服務(wù)器端程序設(shè)計</b></p><p>  以下是服務(wù)器端程序的主函數(shù)部分,在主函數(shù)中,首

49、先創(chuàng)建了一個新的線程,然后按照網(wǎng)絡(luò)編程模型中服務(wù)器端的編程方法進(jìn)行了編程,詳細(xì)程序設(shè)計請參考附件1.</p><p>  void main(void)</p><p><b>  {</b></p><p>  /**************子線程相關(guān)*******************/</p><p>  pt

50、hread_t reader = -1; //read進(jìn)程的進(jìn)程號</p><p>  pthread_mutex_init(&mutex,NULL); //初始化 互斥鎖</p><p><b>  /*初始化數(shù)據(jù)*/</b></p><p>  int i = 0;</p><p>  for(i=0; i

51、<5; i++)</p><p><b>  {</b></p><p>  information[i].name = NAME[i];</p><p>  information[i].age = AGE[i];</p><p>  information[i].number = NUM[i];</p&g

52、t;<p>  information[i].high = HIGH[i];</p><p>  information[i].weigh = WIGHT[i];</p><p><b>  }</b></p><p>  /*創(chuàng)建線程,產(chǎn)生數(shù)據(jù)*/</p><p>  pthread_create(&a

53、mp;reader,NULL,(void*)&writer_function,NULL);</p><p>  /************主線程相關(guān)**********************/</p><p>  //創(chuàng)建socket</p><p>  nListenSock =socket(AF_INET,SOCK_STREAM,IPPROTO_TCP

54、);</p><p>  if(nListenSock<0)</p><p><b>  {</b></p><p>  printf("create listen socket error\n");</p><p><b>  return;</b></p>

55、<p><b>  }</b></p><p>  //設(shè)置socket選項(xiàng)</p><p>  int nValue=1;</p><p>  if(setsockopt(nListenSock,SOL_SOCKET,SO_REUSEADDR,(char*)&nValue,sizeof(int))<0)</p&

56、gt;<p><b>  {</b></p><p>  printf("set option SO_REUSEADDR fail!\n");</p><p>  close(nListenSock);</p><p><b>  return;</b></p><p&

57、gt;<b>  }</b></p><p><b>  //綁定</b></p><p>  struct sockaddr_in localAddr;</p><p>  memset(&localAddr,0x0,sizeof(localAddr));</p><p>  localA

58、ddr.sin_family =AF_INET;</p><p>  localAddr.sin_addr.s_addr =htonl(INADDR_ANY);</p><p>  localAddr.sin_port =htons(10000);</p><p>  if(bind(nListenSock,(struct sockaddr*)&localA

59、ddr,sizeof(struct sockaddr))<0)</p><p><b>  {</b></p><p>  printf("bind liste sock fail!\n");</p><p>  close(nListenSock);</p><p><b>  re

60、turn;</b></p><p><b>  }</b></p><p><b>  //監(jiān)聽</b></p><p>  if(listen(nListenSock,5)<0)</p><p><b>  {</b></p><p>

61、;  printf("listen error!\n");</p><p>  close(nListenSock);</p><p><b>  return;</b></p><p><b>  }</b></p><p>  //創(chuàng)建客戶端的線程</p>&l

62、t;p>  int nSrvThreadId =1;</p><p>  nThreadFlag =1;</p><p>  if(pthread_create((pthread_t*)&nSrvThreadId,NULL,(void*)&serverThreadProc,NULL)<0)</p><p><b>  {<

63、/b></p><p>  printf("create server thread fail!\n");</p><p>  close(nListenSock);</p><p><b>  return;</b></p><p><b>  }</b></p&g

64、t;<p><b>  //等待退出</b></p><p><b>  while(1)</b></p><p><b>  {</b></p><p>  if(pthread_join(nSrvThreadId,NULL)!=0)</p><p><b

65、>  {</b></p><p><b>  return;</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><

66、b>  客戶端程序設(shè)計</b></p><p>  以下是客戶端的程序設(shè)計,代碼片段太過冗長,詳細(xì)的程序設(shè)計請參考附件2。</p><p>  void main(int argc, char** argv)</p><p><b>  {</b></p><p><b>  //創(chuàng)建套接字&

67、lt;/b></p><p>  int sockfd=-1;</p><p>  sockfd =socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);</p><p>  if(sockfd<0)</p><p><b>  {</b></p><p> 

68、 printf("socket create error\n");</p><p><b>  return;</b></p><p><b>  }</b></p><p><b>  ......</b></p><p><b>  //建立

69、連接</b></p><p>  while(1) //建立鏈接</p><p><b>  {</b></p><p>  if(connect(sockfd,</p><p>  (struct sockaddr*)&serverAddr,</p><p>  size

70、of(serverAddr))==0)</p><p><b>  {</b></p><p>  printf("connected\n");</p><p><b>  break;</b></p><p><b>  }</b></p>

71、<p><b>  sleep(1);</b></p><p><b>  }</b></p><p><b>  ......</b></p><p><b>  //創(chuàng)建交互進(jìn)程</b></p><p>  pthread_t ipt_id;

72、</p><p>  if(pthread_create((pthread_t *)&ipt_id,NULL,(void*)&input,NULL)<0)</p><p><b>  {</b></p><p>  printf("create input thread fail!\n");</p

73、><p>  close(ipt_id);</p><p><b>  return;</b></p><p><b>  }</b></p><p><b>  ......</b></p><p><b>  }</b></p

74、><p><b>  綜合測試</b></p><p><b>  功能測試 </b></p><p>  1.運(yùn)行服務(wù)器端程序,處于監(jiān)聽狀態(tài),等待客戶端來連接,當(dāng)有客戶端連接上,輸出連接的客戶端的信息。</p><p>  圖 4-1-1 服務(wù)器運(yùn)行</p><p>  2.運(yùn)

75、行客戶端程序,等待用戶輸入要從數(shù)據(jù)庫中讀取的信息編號,當(dāng)用戶輸入要讀取的信息標(biāo)號的時候,服務(wù)器響應(yīng)客戶端的請求,回復(fù)信息。</p><p>  圖 4-1-2 客戶端運(yùn)行</p><p>  3.在當(dāng)前目錄下生成一個.txt文件,內(nèi)部包含客戶端請求的信息。</p><p>  圖 4-1-3 生成文件</p><p>  4.打開文件,內(nèi)部為

76、請求的信息。</p><p>  圖 4-1-4 文件內(nèi)容</p><p><b>  結(jié)論</b></p><p>  本次課程設(shè)計的內(nèi)容是基于Linux操作系統(tǒng)的多線程網(wǎng)絡(luò)編程,實(shí)現(xiàn)的功能是“生產(chǎn)者”,“消費(fèi)者”模型,建立TCP服務(wù)器,響應(yīng)客戶端請求,并發(fā)送客戶端請求的數(shù)據(jù)。在程序的設(shè)計過程中采用了多線程的編程方式,顯著提高了程序運(yùn)行的效率

77、。</p><p>  客戶端與服務(wù)器通過TCP方式建立連接,使用的通訊函數(shù)接口為套接字,套接字在網(wǎng)絡(luò)編程中有著舉足輕重的地位。通過本次課程設(shè)計,我們創(chuàng)建TCP服務(wù)器線程,響應(yīng)多個客戶端的連接,讀取隊(duì)列/數(shù)組,向客戶端發(fā)送指定“學(xué)號”的數(shù)據(jù);創(chuàng)建TCP客戶端接收線程,連接服務(wù)器并請求指定“學(xué)號”的數(shù)據(jù),接收數(shù)據(jù)并存儲在文件中;在實(shí)現(xiàn)的這個過程中,利用數(shù)據(jù)結(jié)構(gòu)中的隊(duì)列構(gòu)造了數(shù)據(jù)表,方便程序訪問,同時,也方便服務(wù)器端

78、對數(shù)據(jù)的管理。</p><p>  通過本次課程設(shè)計,掌握了Linux下的編程模式和編程方法,熟悉了Linux的基本操作;同時,掌握了開發(fā)環(huán)境的搭建,常用的軟件服務(wù)的安裝,鍛煉了實(shí)際的工程能力;通過多線程編程方法,理解了線程和進(jìn)程的區(qū)別和聯(lián)系,掌握了創(chuàng)建線程和注銷線程的方法;通過對套接字的使用,掌握了在Linux下基于套接字的網(wǎng)絡(luò)編程,理解了Linux下套接字編程在服務(wù)器端和客戶端的編程流程,了解了網(wǎng)絡(luò)模型,提高

79、了解決問題的能力。</p><p><b>  參考文獻(xiàn)</b></p><p>  范展源.深度實(shí)踐嵌入式Linux系統(tǒng)移植.北京:機(jī)械工業(yè)出版社,2015.5</p><p>  宋寶華.Linux設(shè)備驅(qū)動開發(fā)詳解.北京:機(jī)械工業(yè)出版社,2015.7</p><p>  譚浩強(qiáng).C程序設(shè)計.北京:清華大學(xué)出版社,20

80、10.6</p><p>  陳文智.嵌入式系統(tǒng)設(shè)計與原理.北京:清華大學(xué)出版社,2011.5</p><p>  宋敬彬.Liunx網(wǎng)絡(luò)編程.北京:清華大學(xué)出版社,2010.6</p><p>  附錄一 服務(wù)器端程序</p><p>  /********************************************</p

81、><p>  文件名: server.c</p><p>  文件描述: 嵌入式課程設(shè)計程序</p><p>  完成日期:2017年9月8日</p><p><b>  作者:陳凱</b></p><p>  聯(lián)系方式:975500487@qq.com</p><p>  *

82、*******************************************/</p><p>  #include <stdio.h></p><p>  #include <sys/types.h></p><p>  #include <sys/socket.h></p><p>  #in

83、clude <arpa/inet.h></p><p>  #include <string.h></p><p>  #include <pthread.h> </p><p>  #include <stdlib.h></p><p>  #include<sys/time.h>

84、</p><p><b>  /*函數(shù)申明*/</b></p><p>  void writer_function(void);</p><p>  void serverThreadProc(void *);</p><p><b>  //鏈表結(jié)點(diǎn)結(jié)構(gòu)體</b></p><

85、p>  typedef struct _CLIENT_INFO_</p><p><b>  {</b></p><p>  charszClientIp[16];</p><p>  int nClientPort;</p><p>  intnClientSock;</p><

86、p>  struct_CLIENT_INFO_ *pNext;</p><p>  struct_CLIENT_INFO_ *pPre;</p><p>  }CLIENT_INFO;</p><p><b>  /*數(shù)據(jù)類型*/</b></p><p>  typedef struct datatype &l

87、t;/p><p><b>  {</b></p><p>  unsigned char number;</p><p>  unsigned char age;</p><p>  unsigned char high;</p><p>  unsigned char weigh;</p>

88、;<p>  long time;</p><p>  char *name;</p><p>  }Datatype;</p><p>  /****協(xié)議包結(jié)構(gòu)****/</p><p>  typedef struct pro_package</p><p><b>  {</b&

89、gt;</p><p>  char head; //開始標(biāo)志為 設(shè)定為0x7E 1</p><p>  int lenth; //包的數(shù)據(jù)部分長度 4</p><p>  unsigned char flag; //0 : cmd 1:data 1</p><p>  unsigned char sto

90、p; //0 stop 1:send 1</p><p>  unsigned char num; //標(biāo)明發(fā)送信息 1</p><p>  unsigned char data[200]; //數(shù)據(jù)部分 </p><p>  }Pro_package;</p><p><b>  /*創(chuàng)建緩存區(qū)*/&

91、lt;/b></p><p>  typedef struct queue</p><p><b>  {</b></p><p>  Datatype buffer[5]; </p><p>  int b_tail;</p><p>  int b_head;</p>&l

92、t;p><b>  }queue; </b></p><p><b>  /*初始化隊(duì)列*/</b></p><p>  queue Queue = </p><p><b>  {</b></p><p>  .b_tail = 0,</p><p&

93、gt;  .b_head = 0,</p><p><b>  };</b></p><p><b>  /*數(shù)據(jù)初始化*/</b></p><p>  char *NAME[5] = {"wuhao", "chenkai","liumenglin","

94、liujin","liufeng"};</p><p>  unsigned char AGE[5] = {20,21,22,23,24};</p><p>  unsigned char NUM[5] = {1,2,3,4,5};</p><p>  unsigned char HIGH[5] = {175,174,173,175,1

95、65};</p><p>  unsigned char WIGHT[5] = {58, 55, 62, 63, 50};</p><p>  Datatype information[5];</p><p>  /****全局變量***/</p><p>  int nListenSock =-1; //server lisen socke

96、t</p><p>  int nThreadFlag =0; // thread start/stop flag</p><p>  CLIENT_INFO *pClientHead=NULL; //client list header</p><p>  struct timeval sys_time;</p><p>  pthrea

97、d_mutex_t mutex;</p><p>  int buffer_has_item=0;</p><p><b>  //主函數(shù)</b></p><p>  void main(void)</p><p><b>  {</b></p><p>  /*******

98、*******子線程相關(guān)*******************/</p><p>  pthread_t reader = -1; //read進(jìn)程的進(jìn)程號</p><p>  pthread_mutex_init(&mutex,NULL); //初始化 互斥鎖</p><p><b>  /*初始化數(shù)據(jù)*/</b></p>

99、;<p>  int i = 0;</p><p>  for(i=0; i<5; i++)</p><p><b>  {</b></p><p>  information[i].name = NAME[i];</p><p>  information[i].age = AGE[i];</

100、p><p>  information[i].number = NUM[i];</p><p>  information[i].high = HIGH[i];</p><p>  information[i].weigh = WIGHT[i];</p><p><b>  }</b></p><p&g

101、t;  /*創(chuàng)建線程,產(chǎn)生數(shù)據(jù)*/</p><p>  pthread_create(&reader,NULL,(void*)&writer_function,NULL);</p><p>  /************主線程相關(guān)**********************/</p><p>  //創(chuàng)建socket</p><p

102、>  nListenSock =socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);</p><p>  if(nListenSock<0)</p><p><b>  {</b></p><p>  printf("create listen socket error\n");<

103、;/p><p><b>  return;</b></p><p><b>  }</b></p><p>  //設(shè)置socket選項(xiàng)</p><p>  int nValue=1;</p><p>  if(setsockopt(nListenSock,SOL_SOCKET,

104、</p><p>  SO_REUSEADDR,(char*)&nValue,sizeof(int))<0)</p><p><b>  {</b></p><p>  printf("set option SO_REUSEADDR fail!\n");</p><p>  close(

105、nListenSock);</p><p><b>  return;</b></p><p><b>  }</b></p><p><b>  //綁定</b></p><p>  struct sockaddr_in localAddr;</p><p

106、>  memset(&localAddr,0x0,sizeof(localAddr));</p><p>  localAddr.sin_family =AF_INET;</p><p>  localAddr.sin_addr.s_addr =htonl(INADDR_ANY);</p><p>  localAddr.sin_port =htons

107、(10000);</p><p>  if(bind(nListenSock,(struct sockaddr*)&localAddr,sizeof(struct sockaddr))<0)</p><p><b>  {</b></p><p>  printf("bind liste sock fail!\n&quo

108、t;);</p><p>  close(nListenSock);</p><p><b>  return;</b></p><p><b>  }</b></p><p><b>  //監(jiān)聽</b></p><p>  if(listen(nLi

109、stenSock,5)<0)</p><p><b>  {</b></p><p>  printf("listen error!\n");</p><p>  close(nListenSock);</p><p><b>  return;</b></p>

110、<p><b>  }</b></p><p>  //創(chuàng)建客戶端的線程</p><p>  int nSrvThreadId =1;</p><p>  nThreadFlag =1;</p><p>  if(pthread_create((pthread_t*)&nSrvThreadId,NU

111、LL,(void*)&serverThreadProc,NULL)<0)</p><p><b>  {</b></p><p>  printf("create server thread fail!\n");</p><p>  close(nListenSock);</p><p>

112、;<b>  return;</b></p><p><b>  }</b></p><p><b>  //等待退出</b></p><p><b>  while(1)</b></p><p><b>  {</b></p&

113、gt;<p>  if(pthread_join(nSrvThreadId,NULL)!=0)</p><p><b>  {</b></p><p><b>  return;</b></p><p><b>  }</b></p><p><b> 

114、 }</b></p><p><b>  }</b></p><p>  /*處理客戶端函數(shù)*/</p><p>  void serverThreadProc(void *pPram)</p><p><b>  {</b></p><p>  int nMa

115、xFd;</p><p>  fd_set rset,allset;</p><p>  struct timeval timeOut={0,20*1000};</p><p>  FD_ZERO(&allset);</p><p>  FD_SET(nListenSock,&allset);</p><p

116、>  nMaxFd =nListenSock;</p><p>  CLIENT_INFO *pTcpClient;</p><p>  int nSelectR;</p><p>  struct sockaddr_in clientAddr;</p><p>  CLIENT_INFO *pTempClient;</p>

117、<p>  unsigned char ucRcvBuf[100];</p><p>  int nAddrSize =sizeof(clientAddr);</p><p>  Pro_package package; //定義包結(jié)構(gòu)</p><p>  unsigned char send_buffer[200]; //發(fā)送緩存</p&g

118、t;<p>  int verify_flag = 0;</p><p>  while(1) //while 循環(huán)</p><p><b>  {</b></p><p>  rset =allset;</p><p>  nSelectR =select(nMaxFd+1,&rset,NULL

119、,NULL,&timeOut);</p><p>  if(nSelectR==-1) //若發(fā)生錯誤</p><p><b>  {</b></p><p><b>  continue;</b></p><p><b>  }</b></p><

120、;p>  else if(nSelectR==0) //超時</p><p><b>  {</b></p><p><b>  continue;</b></p><p><b>  }</b></p><p>  if(FD_ISSET(nListenSock,&a

121、mp;rset)) // 檢查nListenSock是否在套接字集合中</p><p><b>  {</b></p><p>  printf("accept client!\n");</p><p>  int nConnectSock =accept(nListenSock,(struct sockaddr*)&a

122、mp;clientAddr,&nAddrSize);</p><p>  if(nConnectSock==-1)</p><p><b>  {</b></p><p>  printf("nConnectSock -1\n");</p><p><b>  continue;&l

123、t;/b></p><p><b>  }</b></p><p>  //保存客戶端的信息</p><p>  pTcpClient =(CLIENT_INFO*)malloc(sizeof(CLIENT_INFO));</p><p>  pTcpClient->nClientSock =nConnect

124、Sock;</p><p>  pTcpClient->nClientPort =ntohs(clientAddr.sin_port);</p><p>  strcpy(pTcpClient->szClientIp,inet_ntoa(clientAddr.sin_addr));</p><p>  pTcpClient->pNext =NULL

125、;</p><p>  pTcpClient->pPre =NULL;</p><p>  printf("client connected,ip:%s,port:%d\n",</p><p>  pTcpClient->szClientIp,</p><p>  pTcpClient->nClientP

126、ort);</p><p>  if(pClientHead==NULL)</p><p><b>  {</b></p><p>  pClientHead= pTcpClient;</p><p><b>  }</b></p><p><b>  else&l

127、t;/b></p><p><b>  {</b></p><p>  pTempClient =pClientHead;</p><p>  while(pTempClient->pNext!=NULL)</p><p><b>  {</b></p><p>

128、  pTempClient =pTempClient->pNext;</p><p><b>  }</b></p><p>  pTempClient->pNext =pTcpClient;</p><p>  pTcpClient->pPre =pTempClient;</p><p><b

129、>  }</b></p><p>  //update fd set</p><p>  FD_SET(nConnectSock,&allset);</p><p>  if(nConnectSock>nMaxFd)</p><p><b>  {</b></p><p

130、>  nMaxFd =nConnectSock;</p><p><b>  }</b></p><p><b>  }</b></p><p>  else //對客戶端的服務(wù)</p><p><b>  {</b></p><p>  //f

131、ind the client </p><p>  pTcpClient =pClientHead;</p><p>  while(pTcpClient!=NULL)</p><p><b>  {</b></p><p>  int nRcvSock =pTcpClient->nClientSock;</

132、p><p>  if(FD_ISSET(nRcvSock,&rset)==0)</p><p><b>  {</b></p><p>  pTcpClient =pTcpClient->pNext;</p><p><b>  continue;</b></p><p

溫馨提示

  • 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. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(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

提交評論