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

下載本文檔

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

文檔簡介

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

2、述;在多線程編程中,本文詳細分析了多線程的互斥模型,講解了多種線程之間的同步方法,并在程序設(shè)計中得到體現(xiàn),詳細講述了Linux中的TCP服務(wù)器/客戶端通信程序,并對結(jié)果進行了驗證。</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>  參考文獻21</b></p><p>  附錄一 服務(wù)器端程序22</p><p>  附錄二 客戶端程序32</p><p><b>  緒論</b></p><p>  Linux經(jīng)歷了

9、20多年的發(fā)展,已經(jīng)成為了一個功能強大而穩(wěn)定的操作系統(tǒng),在嵌入式系統(tǒng)中也得到廣泛的運用,伴隨著物聯(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ǔ)上延伸和擴展來的物聯(lián)網(wǎng)技術(shù),正逐漸改變著我們的世界?;ヂ?lián)網(wǎng)在現(xiàn)實生活中的應(yīng)用很廣

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

11、多的進步,會影響生活中的方方面面。</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)強國,我國到目前為止,已經(jīng)誕生了一大批優(yōu)秀的互聯(lián)網(wǎng)企業(yè),全世界都將在互聯(lián)網(wǎng)的推動下,進入一個全新的時代。</p><p><b>  主要研究內(nèi)容</b></p><p>  設(shè)計TCP服務(wù)器程序,使用多線程實現(xiàn)”生產(chǎn)者-消費者“模型,建立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(),可使用隊列/多維數(shù)組存儲數(shù)據(jù);</p><p>  創(chuàng)建TCP服務(wù)器線程,響應(yīng)多個客戶端的連接,讀取隊列/數(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è)知識的熟練運用,理解Linux網(wǎng)絡(luò)編程的

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

16、 書寫技術(shù)報告和編制技術(shù)資料的能力。</p><p><b>  課題要求</b></p><p>  使用多線程實現(xiàn)”生產(chǎn)者-消費者“模型,建立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),可使用隊列/多維數(shù)組存儲數(shù)據(jù)。理解常用的數(shù)據(jù)結(jié)構(gòu),熟練掌握C編程語言。</p><p>  創(chuàng)建TCP服務(wù)器線程,響應(yīng)多個客戶端的連接,讀取隊列/數(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)的基本思想,掌握編程語言,理解多線程編程在實際工程中的應(yīng)用。</p><p><b>  環(huán)境搭建</b></p><p

19、>  Ubuntu系統(tǒng)安裝</p><p>  考慮到Windows系統(tǒng)的普及程度,本課程實際將利用虛擬機來進行開發(fā),首先我們需要搭建虛擬機開發(fā)環(huán)境。</p><p><b>  創(chuàng)建虛擬機</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ò)中的計算機之間通過TCP/IP網(wǎng)絡(luò)共享資源。在NFS的應(yīng)用中,本地NFS的客戶端應(yīng)用可以透明地讀寫位于遠端NFS服務(wù)器上的文件,就像訪問本地文件一樣。</p><p><b&g

23、t;  NFS安裝</b></p><p>  1.NFS是網(wǎng)絡(luò)文件系統(tǒng)系統(tǒng)的縮寫,可以用于Linux和Linux之間傳遞文件,實現(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 主機可以通過網(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ò)接口層的主要功能是提供二進制傳輸和介質(zhì)訪問的功能;網(wǎng)

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

31、數(shù)據(jù)包加上包頭,IP協(xié)議在每個包頭上再加上接收端主機地址,這樣數(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ò)進行不同的設(shè)置,且每個節(jié)點一

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

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

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

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

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

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

38、的次數(shù),而檢錯互斥鎖則為快速互斥鎖的非阻塞版本,它會立即返回并返回一個錯誤信息。</p><p>  互斥鎖機制主要包括下面的基本函數(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原子操作,它廣泛用于進程或線程間的同步

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

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

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

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

44、 Server編程模型</p><p>  進行版本協(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>  進行版本協(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ù)器程序,使用多線程實現(xiàn)”生產(chǎn)者-消費者“模型,建立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),可使用隊列/多維數(shù)組存儲數(shù)據(jù)。</p><p>  2.創(chuàng)建TCP服務(wù)器線程,響應(yīng)多個客戶端的連接,讀取隊列/數(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ù)器端的編程方法進行了編程,詳細程序設(shè)計請參考附件1.</p><p>  void main(void)</p><p><b>  {</b></p><p>  /**************子線程相關(guān)*******************/</p><p>  pt

50、hread_t reader = -1; //read進程的進程號</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選項</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è)計,代碼片段太過冗長,詳細的程序設(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)建交互進程</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.運行服務(wù)器端程序,處于監(jiān)聽狀態(tài),等待客戶端來連接,當(dāng)有客戶端連接上,輸出連接的客戶端的信息。</p><p>  圖 4-1-1 服務(wù)器運行</p><p>  2.運

75、行客戶端程序,等待用戶輸入要從數(shù)據(jù)庫中讀取的信息編號,當(dāng)用戶輸入要讀取的信息標(biāo)號的時候,服務(wù)器響應(yīng)客戶端的請求,回復(fù)信息。</p><p>  圖 4-1-2 客戶端運行</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ò)編程,實現(xiàn)的功能是“生產(chǎn)者”,“消費者”模型,建立TCP服務(wù)器,響應(yīng)客戶端請求,并發(fā)送客戶端請求的數(shù)據(jù)。在程序的設(shè)計過程中采用了多線程的編程方式,顯著提高了程序運行的效率

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

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

79、了解決問題的能力。</p><p><b>  參考文獻</b></p><p>  范展源.深度實踐嵌入式Linux系統(tǒng)移植.北京:機械工業(yè)出版社,2015.5</p><p>  宋寶華.Linux設(shè)備驅(qū)動開發(fā)詳解.北京:機械工業(yè)出版社,2015.7</p><p>  譚浩強.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é)點結(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>  /*初始化隊列*/</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進程的進程號</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選項</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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論