嵌入式課程設(shè)計(jì)_第1頁(yè)
嵌入式課程設(shè)計(jì)_第2頁(yè)
嵌入式課程設(shè)計(jì)_第3頁(yè)
嵌入式課程設(shè)計(jì)_第4頁(yè)
嵌入式課程設(shè)計(jì)_第5頁(yè)
已閱讀5頁(yè),還剩38頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、 成都學(xué)院(成都大學(xué))課程設(shè)計(jì)報(bào)告linux TCP服務(wù)器/客戶端通信程序摘要:隨著計(jì)算機(jī)網(wǎng)絡(luò)的不斷發(fā)展,網(wǎng)絡(luò)編程變得越來(lái)越重要,除了簡(jiǎn)單的WEB編程外,還包括利用套接字(Socket)進(jìn)行客戶/服務(wù)器應(yīng)用程序的設(shè)計(jì)。本文先對(duì)與套接字相關(guān)的概念和函數(shù)作了一般性介紹,并提出多線程的編程方法和設(shè)計(jì)流程,也就具體的工程實(shí)例進(jìn)行了流程分析。本文中,對(duì)計(jì)算機(jī)的網(wǎng)絡(luò)模型進(jìn)行了簡(jiǎn)要的分析,并對(duì)TCP的握手模型進(jìn)行了概述;在多線程編程中,本文詳細(xì)分析了多線程的互斥模型,講解了多種線程之間的同步方法,并在程序設(shè)計(jì)中得到體現(xiàn),詳細(xì)講述了Linux中的TCP服務(wù)器/客戶端通信程序,并對(duì)結(jié)果進(jìn)行了驗(yàn)證。關(guān)鍵字:網(wǎng)絡(luò)編

2、程 ;多線程;套接字目 錄緒論11. 課程背景12. 選題的目的和意義13. 國(guó)內(nèi)外研究現(xiàn)狀14. 主要研究?jī)?nèi)容1第1章 需求分析31.1 設(shè)計(jì)目的31.2 課題要求31.3 任務(wù)分析3第2章 環(huán)境搭建42.1 Ubuntu系統(tǒng)安裝42.2 開發(fā)環(huán)境搭建72.2.1 NFS環(huán)境介紹72.2.2 NFS安裝72.2.3 掛載NFS文件系統(tǒng)72.2.4 交叉工具安裝8第3章 軟件設(shè)計(jì)93.1 TCP/IP協(xié)議93.1.1 網(wǎng)絡(luò)模型93.1.2 TCP連接93.2 多線程編程103.3 Socket網(wǎng)絡(luò)編程模型123.3.1 TCP Server編程模型123.3.2 TCP Client編程模型1

3、33.4 程序設(shè)計(jì)133.4.1 主要內(nèi)容133.4.2 服務(wù)器端程序設(shè)計(jì)143.4.3 客戶端程序設(shè)計(jì)16第4章 綜合測(cè)試184.1 功能測(cè)試18第5章 結(jié)論20參考文獻(xiàn)21附錄一 服務(wù)器端程序22附錄二 客戶端程序32II 成都學(xué)院(成都大學(xué))課程設(shè)計(jì)緒論Linux經(jīng)歷了20多年的發(fā)展,已經(jīng)成為了一個(gè)功能強(qiáng)大而穩(wěn)定的操作系統(tǒng),在嵌入式系統(tǒng)中也得到廣泛的運(yùn)用,伴隨著物聯(lián)網(wǎng)技術(shù)的普及,網(wǎng)絡(luò)通信在嵌入式系統(tǒng)中扮演著舉足輕重的作用。1. 課程背景隨著時(shí)代的發(fā)展,網(wǎng)絡(luò)通信在我們的生活中愈來(lái)愈重要,在互聯(lián)網(wǎng)技術(shù)基礎(chǔ)上延伸和擴(kuò)展來(lái)的物聯(lián)網(wǎng)技術(shù),正逐漸改變著我們的世界?;ヂ?lián)網(wǎng)在現(xiàn)實(shí)生活中的應(yīng)用很廣泛,互聯(lián)

4、網(wǎng)給我們的現(xiàn)實(shí)生活帶來(lái)了很大的方便;互聯(lián)網(wǎng)是全球性的,這也就意味著我們能夠打破時(shí)空的界限,通過(guò)互聯(lián)網(wǎng)接觸到世界的每一個(gè)角落;因?yàn)榛ヂ?lián)網(wǎng)的強(qiáng)大力量,這個(gè)時(shí)代的文明發(fā)展得到極大地提高。2. 選題的目的和意義由于互聯(lián)網(wǎng)超乎尋常的強(qiáng)大力量,改變了這個(gè)時(shí)代的交流方式,改變著人們的生活,未來(lái),我們還將在互聯(lián)網(wǎng)領(lǐng)域得到更多的進(jìn)步,會(huì)影響生活中的方方面面。3. 國(guó)內(nèi)外研究現(xiàn)狀互聯(lián)網(wǎng)從誕生至今,讓人類文明得到巨大的推動(dòng),伴隨著互聯(lián)網(wǎng)的發(fā)展,各種依托互聯(lián)網(wǎng)的技術(shù)得到迅速發(fā)展,Linux操作系統(tǒng)依據(jù)其優(yōu)良的性能和網(wǎng)絡(luò)功能,在各個(gè)領(lǐng)域都得到極大的普及。21世紀(jì),是互聯(lián)網(wǎng)發(fā)展的有一個(gè)階段,我們國(guó)家已經(jīng)將互聯(lián)網(wǎng)的發(fā)展提升

5、到了戰(zhàn)略高度,明確表示要建成互聯(lián)網(wǎng)強(qiáng)國(guó),我國(guó)到目前為止,已經(jīng)誕生了一大批優(yōu)秀的互聯(lián)網(wǎng)企業(yè),全世界都將在互聯(lián)網(wǎng)的推動(dòng)下,進(jìn)入一個(gè)全新的時(shí)代。4. 主要研究?jī)?nèi)容設(shè)計(jì)TCP服務(wù)器程序,使用多線程實(shí)現(xiàn)”生產(chǎn)者-消費(fèi)者“模型,建立TCP服務(wù)器,響應(yīng)客戶端請(qǐng)求,發(fā)送客戶端指定的請(qǐng)求數(shù)據(jù)。主要包括以下內(nèi)容:(1) 創(chuàng)建線程持續(xù)產(chǎn)生數(shù)據(jù),數(shù)據(jù)包含(學(xué)號(hào),姓名(拼音),年齡,身高,體重,當(dāng)前系統(tǒng)時(shí)間(納秒數(shù))使用gettimeofday(),可使用隊(duì)列/多維數(shù)組存儲(chǔ)數(shù)據(jù);(2) 創(chuàng)建TCP服務(wù)器線程,響應(yīng)多個(gè)客戶端的連接,讀取隊(duì)列/數(shù)組,向客戶端發(fā)送指定“學(xué)號(hào)”的數(shù)據(jù)。設(shè)計(jì)TCP服務(wù)器程序;(3) 創(chuàng)建TCP客

6、戶端接收線程,連接服務(wù)器并請(qǐng)求指定“學(xué)號(hào)”的數(shù)據(jù),接收數(shù)據(jù)并存儲(chǔ)在文件中。要求存儲(chǔ)有意義的數(shù)據(jù),由于TCP是基于字節(jié)流的特征,需要做組包處理;第1章 需求分析1.1 設(shè)計(jì)目的通過(guò)對(duì)專業(yè)知識(shí)的熟練運(yùn)用,理解Linux網(wǎng)絡(luò)編程的流程,了解互聯(lián)網(wǎng)的基本架構(gòu),熟悉多線程編程的思想。同時(shí),通過(guò)本課程設(shè)計(jì),可以培養(yǎng)以下能力:(1) 獨(dú)立工作能力與創(chuàng)造力;(2) 綜合運(yùn)用專業(yè)及基礎(chǔ)知識(shí)的能力;(3) 解決實(shí)際工程技術(shù)問(wèn)題的能力;(4) 查閱圖書資料、產(chǎn)品手冊(cè)和各種工具書的能力;(5) 書寫技術(shù)報(bào)告和編制技術(shù)資料的能力。1.2 課題要求使用多線程實(shí)現(xiàn)”生產(chǎn)者-消費(fèi)者“模型,建立TCP服務(wù)器,響應(yīng)客戶端請(qǐng)求,發(fā)

7、送客戶端指定的請(qǐng)求數(shù)據(jù)。1.3 任務(wù)分析創(chuàng)建線程持續(xù)產(chǎn)生數(shù)據(jù),數(shù)據(jù)包含(學(xué)號(hào),姓名(拼音),年齡,身高,體重,當(dāng)前系統(tǒng)時(shí)間(納秒數(shù))使用gettimeofday),可使用隊(duì)列/多維數(shù)組存儲(chǔ)數(shù)據(jù)。理解常用的數(shù)據(jù)結(jié)構(gòu),熟練掌握C編程語(yǔ)言。創(chuàng)建TCP服務(wù)器線程,響應(yīng)多個(gè)客戶端的連接,讀取隊(duì)列/數(shù)組,向客戶端發(fā)送指定“學(xué)號(hào)”的數(shù)據(jù),設(shè)計(jì)TCP服務(wù)器程序,掌握網(wǎng)絡(luò)編程中服務(wù)器端的編程流程。創(chuàng)建TCP客戶端接收線程,連接服務(wù)器并請(qǐng)求指定“學(xué)號(hào)”的數(shù)據(jù),接收數(shù)據(jù)并存儲(chǔ)在文件中。要求存儲(chǔ)有意義的數(shù)據(jù),由于TCP是基于字節(jié)流的特征,需要做組包處理。掌握網(wǎng)絡(luò)編程中客戶端的編程流程。最終的目的是熟練掌握網(wǎng)絡(luò)編程的編

8、程方法,理解常用的數(shù)據(jù)結(jié)構(gòu)的基本思想,掌握編程語(yǔ)言,理解多線程編程在實(shí)際工程中的應(yīng)用。第2章 環(huán)境搭建2.1 Ubuntu系統(tǒng)安裝考慮到Windows系統(tǒng)的普及程度,本課程實(shí)際將利用虛擬機(jī)來(lái)進(jìn)行開發(fā),首先我們需要搭建虛擬機(jī)開發(fā)環(huán)境。1. 創(chuàng)建虛擬機(jī)圖2. 選擇操作系統(tǒng) 圖3.配置處理器和內(nèi)存圖圖4. 安裝系統(tǒng)圖5. 安裝成功界面圖2.2 開發(fā)環(huán)境搭建2.2.1 NFS環(huán)境介紹NFS(Network File System)即網(wǎng)絡(luò)文件系統(tǒng),是FreeBSD支持的文件系統(tǒng)中的一種,它允許網(wǎng)絡(luò)中的計(jì)算機(jī)之間通過(guò)TCP/IP網(wǎng)絡(luò)共享資源。在NFS的應(yīng)用中,本地NFS的客戶端應(yīng)用可以透明地讀寫位于遠(yuǎn)端N

9、FS服務(wù)器上的文件,就像訪問(wèn)本地文件一樣。2.2.2 NFS安裝1.NFS是網(wǎng)絡(luò)文件系統(tǒng)系統(tǒng)的縮寫,可以用于Linux和Linux之間傳遞文件,實(shí)現(xiàn)數(shù)據(jù)共享。安裝命令如下: apt-get install nfs-kernel-server2.修改配置文件打開/etc/exports文件,增加mount -t nfs/NFS (rw,sync,no_root_squash,no_subtree_check)開發(fā)板和其他 Linux 主機(jī)可以通過(guò)網(wǎng)絡(luò)訪問(wèn)/NFS 目錄。3.啟動(dòng)NFSsudo service rpcbind start sudo service nfs-kernel-server

10、 start2.2.3 掛載NFS文件系統(tǒng)mount -t nfs -o intr,nolock,rsize=1024,wsize=1024 6:/opt/ /mnt2.2.4 交叉工具安裝1.在/usr/local/下建立交叉編譯器的安裝目錄arm:sudo  mkdir /usr/local/arm2.將下載的交叉編譯器包解壓到/usr/local/arm目錄下:sudo tar jxvf cross-4.2.2-eabi.tar.bz2 -C /usr/local/arm/ 3.解壓成功后,修改PATH環(huán)境變量:sudo vim  /e

11、tc/profile在文件為加入交叉編譯器arm-linux-所在的路徑:4.更新一下配置文件/etc/profile:source /etc/profile第3章 軟件設(shè)計(jì)3.1 TCP/IP協(xié)議3.1.1 網(wǎng)絡(luò)模型 圖 3-1-1 網(wǎng)絡(luò)模型如圖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èn)的功能;網(wǎng)絡(luò)層負(fù)責(zé)IP尋址和路由,其中要考慮路由算法,擁塞控制等問(wèn)題;傳輸層負(fù)責(zé)應(yīng)用程序之間的連接;3.1.2 TCP連接TCP IP一般通過(guò)internet串行線路協(xié)議SLIP或點(diǎn)對(duì)點(diǎn)協(xié)議PPP在串行線上進(jìn)行數(shù)

12、據(jù)傳送。TCP/IP協(xié)議的基本傳輸單位是數(shù)據(jù)包 (datagram)。TCP協(xié)議負(fù)責(zé)把數(shù)據(jù)分成若干個(gè)數(shù)據(jù)包/段,并給每個(gè)數(shù)據(jù)包加上包頭,IP協(xié)議在每個(gè)包頭上再加上接收端主機(jī)地址,這樣數(shù)據(jù)找到自己要去的地方。如果傳輸過(guò)程中出現(xiàn)數(shù)據(jù)丟失、數(shù)據(jù)失真等情況,TCP協(xié)議會(huì)自動(dòng)要求數(shù)據(jù)重新傳輸并重新組包。TCP協(xié)議保證數(shù)據(jù)傳輸?shù)馁|(zhì)量,IP協(xié)議保證數(shù)據(jù)的傳輸。數(shù)據(jù)在傳輸時(shí)每通過(guò)一層就要在數(shù)據(jù)上加個(gè)包頭,其中數(shù)據(jù)供接收端同一層協(xié)議使用,而在接收端每經(jīng)過(guò)一層要把用過(guò)的包頭去掉,這樣來(lái)保證傳輸數(shù)據(jù)的格式完全一致。TCP/IP協(xié)議需要針對(duì)不同的網(wǎng)絡(luò)進(jìn)行不同的設(shè)置,且每個(gè)節(jié)點(diǎn)一般需要一個(gè)“IP地址”、一個(gè)“子網(wǎng)掩碼”

13、、一個(gè)“默認(rèn)網(wǎng)關(guān)”。不過(guò)可以通過(guò)動(dòng)態(tài)主機(jī)配置協(xié)議(DHCP),給客戶端自動(dòng)分配一個(gè)IP地址,這樣避免了出錯(cuò)也簡(jiǎn)化了TCP/IP協(xié)議的設(shè)置。如圖3-1-2所示,TCP是通過(guò)3次握手建立的:1. 客戶端給服務(wù)器發(fā)送SYN(syn = j)包,進(jìn)入SYN_SEND狀態(tài)。2. 服務(wù)器接收到SYNC包,確認(rèn)客戶的SYN(ack = j+1),同時(shí)自己也發(fā)送一個(gè)SYN包(syn = k),把它倆都發(fā)送出去,服務(wù)器進(jìn)入SYN_SEND狀態(tài)。3. 客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送ACK(ack = k+1),客戶端和服務(wù)器都進(jìn)入ESTABLISHED狀態(tài)。此時(shí),連接已經(jīng)建立完畢,可以相互發(fā)送發(fā)

14、送消息。圖 3-1-2 三次握手示意圖3.2 多線程編程進(jìn)程是系統(tǒng)中程序執(zhí)行和資源分配的基本單位。每個(gè)進(jìn)程都擁有自己的數(shù)據(jù)段、代碼段和堆棧段,這就造成了進(jìn)程在進(jìn)行切換等操作時(shí)都需要有比較復(fù)雜的上下文切換等動(dòng)作。為了進(jìn)一步減少處理機(jī)的空轉(zhuǎn)時(shí)間,支持多處理器以及減少上下文切換開銷,進(jìn)程在演化中出現(xiàn)了另一個(gè)概念線程。它是進(jìn)程內(nèi)獨(dú)立的一條運(yùn)行路線,處理器調(diào)度的最小單元,也可以稱為輕量級(jí)進(jìn)程。線程可以對(duì)進(jìn)程的內(nèi)存空間和資源進(jìn)行訪問(wèn),并與同一進(jìn)程中的其他線程共享。因此,線程的上下文切換的開銷比創(chuàng)建進(jìn)程小很多。同進(jìn)程一樣,線程也將相關(guān)的執(zhí)行狀態(tài)和存儲(chǔ)變量放在線程控制表內(nèi)。一個(gè)進(jìn)程可以有多個(gè)線程,也就是有多個(gè)

15、線程控制表及堆棧寄存器,但卻共享一個(gè)用戶地址空間。要注意的是,由于線程共享了進(jìn)程的資源和地址空間,因此,任何線程對(duì)系統(tǒng)資源的操作都會(huì)給其他線程帶來(lái)影響。由此可知,多線程中的同步是非常重要的問(wèn)題,以下是線程同步用到的一些方法:1. 互斥鎖互斥鎖是用一種簡(jiǎn)單的加鎖方法來(lái)控制對(duì)共享資源的原子操作。這個(gè)互斥鎖只有兩種狀態(tài),也就是上鎖和解鎖,可以把互斥鎖看作某種意義上的全局變量。在同一時(shí)刻只能有一個(gè)線程掌握某個(gè)互斥鎖,擁有上鎖狀態(tài)的線程能夠?qū)蚕碣Y源進(jìn)行操作。若其他線程希望上鎖一個(gè)已經(jīng)被上鎖的互斥鎖,則該線程就會(huì)掛起,直到上鎖的線程釋放掉互斥鎖為止。可以說(shuō),這把互斥鎖保證讓每個(gè)線程對(duì)共享資源按順序進(jìn)行原

16、子操作?;コ怄i可以分為快速互斥鎖、遞歸互斥鎖和檢錯(cuò)互斥鎖。這三種鎖的區(qū)別主要在于其他未占有互斥鎖的線程在希望得到互斥鎖時(shí)是否需要阻塞等待??焖冁i是指調(diào)用線程會(huì)阻塞直至擁有互斥鎖的線程解鎖為止。遞歸互斥鎖能夠成功地返回,并且增加調(diào)用線程在互斥上加鎖的次數(shù),而檢錯(cuò)互斥鎖則為快速互斥鎖的非阻塞版本,它會(huì)立即返回并返回一個(gè)錯(cuò)誤信息?;コ怄i機(jī)制主要包括下面的基本函數(shù):1) 互斥鎖初始化:pthread_mutex_init()2) 互斥鎖上鎖:pthread_mutex_lock()3) 互斥鎖判斷上鎖:pthread_mutex_trylock()4) 互斥鎖解鎖:pthread_mutex_unlo

17、ck()5) 消除互斥鎖:pthread_mutex_destroy()2. 信號(hào)量信號(hào)量也就是操作系統(tǒng)中所用到的PV原子操作,它廣泛用于進(jìn)程或線程間的同步與互斥。信號(hào)量本質(zhì)上是一個(gè)非負(fù)的整數(shù)計(jì)數(shù)器,它被用來(lái)控制對(duì)公共資源的訪問(wèn)。PV原子操作是對(duì)整數(shù)計(jì)數(shù)器信號(hào)量sem的操作。一次P操作使sem減一,而一次V操作使sem加一。進(jìn)程(或線程)根據(jù)信號(hào)量的值來(lái)判斷是否對(duì)公共資源具有訪問(wèn)權(quán)限。當(dāng)信號(hào)量sem的值大于等于零時(shí),該進(jìn)程(或線程)具有公共資源的訪問(wèn)權(quán)限;相反,當(dāng)信號(hào)量sem的值小于零時(shí),該進(jìn)程(或線程)就將阻塞直到信號(hào)量sem的值大于等于0為止。信號(hào)量機(jī)制主要包括下面的基本函數(shù):1) 創(chuàng)建信

18、號(hào)量: sem_init()2) 等待信號(hào)量:sem_wait()和sem_trywait()3) 喚醒進(jìn)程:sem_post()4) 獲取信號(hào)量: sem_getvalue()5) 刪除信號(hào)量: sem_destroy()3.3 Socket網(wǎng)絡(luò)編程模型在Linux中的網(wǎng)絡(luò)編程是通過(guò)socket接口來(lái)進(jìn)行的。socket是一種特殊的I/O接口,它也是一種文件描述符。它是一種常用的進(jìn)程之間通信機(jī)制,通過(guò)它不僅能實(shí)現(xiàn)本地機(jī)器上的進(jìn)程之間的通信,而且通過(guò)網(wǎng)絡(luò)能夠在不同機(jī)器上的進(jìn)程之間進(jìn)行通信。源IP地址和目的IP地址以及源端口號(hào)和目的端口號(hào)的組合稱為套接字。其用于標(biāo)識(shí)客戶端請(qǐng)求的服務(wù)器和服務(wù),它是

19、網(wǎng)絡(luò)通信過(guò)程中端點(diǎn)的抽象表示,包含進(jìn)行網(wǎng)絡(luò)通信必需的五種信息:連接使用的協(xié)議,本地主機(jī)的IP地址,本地進(jìn)程的協(xié)議端口,遠(yuǎn)地主機(jī)的IP地址,遠(yuǎn)地進(jìn)程的協(xié)議端口。3.3.1 TCP Server編程模型設(shè)置為監(jiān)聽狀態(tài)進(jìn)行版本協(xié)商創(chuàng)建套接字接受客戶端的連接請(qǐng)求接收或者發(fā)送數(shù)據(jù)關(guān)閉套接字圖 3-2-1 Server編程模型1) 進(jìn)行版本協(xié)商(WSAStartup)2) 創(chuàng)建一個(gè)套接字(socket()3) 將套接字設(shè)為監(jiān)聽狀態(tài)(listen()4) 接受客戶端的連接請(qǐng)求(accept()5) 發(fā)送或者接收數(shù)據(jù)(send()/recv()6) 關(guān)閉套接字(close()3.3.2 TCP Client編

20、程模型連接到服務(wù)器進(jìn)行版本協(xié)商創(chuàng)建套接字接收或者發(fā)送數(shù)據(jù)關(guān)閉套接字圖 3-2-2 Client編程模型1) 進(jìn)行版本協(xié)商(WSAStartup)2) 創(chuàng)建一個(gè)套接字(socket()3) 連接到服務(wù)器(connect()4) 發(fā)送或者接收函數(shù)(send()/recv()5) 關(guān)閉套接字(close()3.4 程序設(shè)計(jì)3.4.1 主要內(nèi)容設(shè)計(jì)TCP服務(wù)器程序,使用多線程實(shí)現(xiàn)”生產(chǎn)者-消費(fèi)者“模型,建立TCP服務(wù)器,響應(yīng)客戶端請(qǐng)求,發(fā)送客戶端指定的請(qǐng)求數(shù)據(jù)。1.創(chuàng)建線程持續(xù)產(chǎn)生數(shù)據(jù),數(shù)據(jù)包含(學(xué)號(hào),姓名(拼音),年齡,身高,體重,當(dāng)前系統(tǒng)時(shí)間(納秒數(shù))使用gettimeofday),可使用隊(duì)列/多

21、維數(shù)組存儲(chǔ)數(shù)據(jù)。2.創(chuàng)建TCP服務(wù)器線程,響應(yīng)多個(gè)客戶端的連接,讀取隊(duì)列/數(shù)組,向客戶端發(fā)送指定“學(xué)號(hào)”的數(shù)據(jù)。設(shè)計(jì)TCP服務(wù)器程序。3.創(chuàng)建TCP客戶端接收線程,連接服務(wù)器并請(qǐng)求指定“學(xué)號(hào)”的數(shù)據(jù),接收數(shù)據(jù)并存儲(chǔ)在文件中。要求存儲(chǔ)有意義的數(shù)據(jù),由于TCP是基于字節(jié)流的特征,需要做組包處理3.4.2 服務(wù)器端程序設(shè)計(jì)以下是服務(wù)器端程序的主函數(shù)部分,在主函數(shù)中,首先創(chuàng)建了一個(gè)新的線程,然后按照網(wǎng)絡(luò)編程模型中服務(wù)器端的編程方法進(jìn)行了編程,詳細(xì)程序設(shè)計(jì)請(qǐng)參考附件1.void main(void)/*子線程相關(guān)*/pthread_t reader = -1; /read進(jìn)程的進(jìn)程號(hào)pthread_mu

22、tex_init(&mutex,NULL); /初始化 互斥鎖/*初始化數(shù)據(jù)*/int i = 0;for(i=0; i<5; i+) = NAMEi;informationi.age = AGEi;informationi.number = NUMi;informationi.high = HIGHi;informationi.weigh = WIGHTi; /*創(chuàng)建線程,產(chǎn)生數(shù)據(jù)*/pthread_create(&reader,NULL,(void*)&writer_function,NULL); /*主線程相關(guān)*/創(chuàng)建soc

23、ketnListenSock =socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(nListenSock<0)printf("create listen socket errorn");return;/設(shè)置socket選項(xiàng)int nValue=1;if(setsockopt(nListenSock,SOL_SOCKET,SO_REUSEADDR,(char*)&nValue,sizeof(int)<0)printf("set option SO_REUSEADDR fail!n");close(nL

24、istenSock);return;/綁定struct sockaddr_in localAddr;memset(&localAddr,0x0,sizeof(localAddr);localAddr.sin_family =AF_INET;localAddr.sin_addr.s_addr =htonl(INADDR_ANY);localAddr.sin_port =htons(10000);if(bind(nListenSock,(struct sockaddr*)&localAddr,sizeof(struct sockaddr)<0)printf("bin

25、d liste sock fail!n");close(nListenSock);return;/監(jiān)聽if(listen(nListenSock,5)<0)printf("listen error!n");close(nListenSock);return;/創(chuàng)建客戶端的線程int nSrvThreadId =1;nThreadFlag =1;if(pthread_create(pthread_t*)&nSrvThreadId,NULL,(void*)&serverThreadProc,NULL)<0)printf("crea

26、te server thread fail!n");close(nListenSock);return;/等待退出while(1)if(pthread_join(nSrvThreadId,NULL)!=0)return;3.4.3 客戶端程序設(shè)計(jì)以下是客戶端的程序設(shè)計(jì),代碼片段太過(guò)冗長(zhǎng),詳細(xì)的程序設(shè)計(jì)請(qǐng)參考附件2。void main(int argc, char* argv)/創(chuàng)建套接字int sockfd=-1;sockfd =socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(sockfd<0)printf("socket cre

27、ate errorn");return;./建立連接while(1) /建立鏈接if(connect(sockfd,(struct sockaddr*)&serverAddr,sizeof(serverAddr)=0)printf("connectedn");break;sleep(1);./創(chuàng)建交互進(jìn)程pthread_t ipt_id;if(pthread_create(pthread_t *)&ipt_id,NULL,(void*)&input,NULL)<0)printf("create input thread fa

28、il!n");close(ipt_id);return;.第4章 綜合測(cè)試4.1 功能測(cè)試 1.運(yùn)行服務(wù)器端程序,處于監(jiān)聽狀態(tài),等待客戶端來(lái)連接,當(dāng)有客戶端連接上,輸出連接的客戶端的信息。圖 4-1-1 服務(wù)器運(yùn)行2.運(yùn)行客戶端程序,等待用戶輸入要從數(shù)據(jù)庫(kù)中讀取的信息編號(hào),當(dāng)用戶輸入要讀取的信息標(biāo)號(hào)的時(shí)候,服務(wù)器響應(yīng)客戶端的請(qǐng)求,回復(fù)信息。圖 4-1-2 客戶端運(yùn)行3.在當(dāng)前目錄下生成一個(gè).txt文件,內(nèi)部包含客戶端請(qǐng)求的信息。圖 4-1-3 生成文件4.打開文件,內(nèi)部為請(qǐng)求的信息。圖 4-1-4 文件內(nèi)容第5章 結(jié)論本次課程設(shè)計(jì)的內(nèi)容是基于Linux操作系統(tǒng)的多線程網(wǎng)絡(luò)編程,實(shí)現(xiàn)的

29、功能是“生產(chǎn)者”,“消費(fèi)者”模型,建立TCP服務(wù)器,響應(yīng)客戶端請(qǐng)求,并發(fā)送客戶端請(qǐng)求的數(shù)據(jù)。在程序的設(shè)計(jì)過(guò)程中采用了多線程的編程方式,顯著提高了程序運(yùn)行的效率。客戶端與服務(wù)器通過(guò)TCP方式建立連接,使用的通訊函數(shù)接口為套接字,套接字在網(wǎng)絡(luò)編程中有著舉足輕重的地位。通過(guò)本次課程設(shè)計(jì),我們創(chuàng)建TCP服務(wù)器線程,響應(yīng)多個(gè)客戶端的連接,讀取隊(duì)列/數(shù)組,向客戶端發(fā)送指定“學(xué)號(hào)”的數(shù)據(jù);創(chuàng)建TCP客戶端接收線程,連接服務(wù)器并請(qǐng)求指定“學(xué)號(hào)”的數(shù)據(jù),接收數(shù)據(jù)并存儲(chǔ)在文件中;在實(shí)現(xiàn)的這個(gè)過(guò)程中,利用數(shù)據(jù)結(jié)構(gòu)中的隊(duì)列構(gòu)造了數(shù)據(jù)表,方便程序訪問(wèn),同時(shí),也方便服務(wù)器端對(duì)數(shù)據(jù)的管理。通過(guò)本次課程設(shè)計(jì),掌握了Linux

30、下的編程模式和編程方法,熟悉了Linux的基本操作;同時(shí),掌握了開發(fā)環(huán)境的搭建,常用的軟件服務(wù)的安裝,鍛煉了實(shí)際的工程能力;通過(guò)多線程編程方法,理解了線程和進(jìn)程的區(qū)別和聯(lián)系,掌握了創(chuàng)建線程和注銷線程的方法;通過(guò)對(duì)套接字的使用,掌握了在Linux下基于套接字的網(wǎng)絡(luò)編程,理解了Linux下套接字編程在服務(wù)器端和客戶端的編程流程,了解了網(wǎng)絡(luò)模型,提高了解決問(wèn)題的能力。參考文獻(xiàn)1 范展源.深度實(shí)踐嵌入式Linux系統(tǒng)移植.北京:機(jī)械工業(yè)出版社,2015.52 宋寶華.Linux設(shè)備驅(qū)動(dòng)開發(fā)詳解.北京:機(jī)械工業(yè)出版社,2015.73 譚浩強(qiáng).C程序設(shè)計(jì).北京:清華大學(xué)出版社,2010.64 陳文智.嵌入

31、式系統(tǒng)設(shè)計(jì)與原理.北京:清華大學(xué)出版社,2011.55 宋敬彬.Liunx網(wǎng)絡(luò)編程.北京:清華大學(xué)出版社,2010.6附錄一 服務(wù)器端程序/*文件名: server.c文件描述: 嵌入式課程設(shè)計(jì)程序完成日期:2017年9月8日作者:陳凱*/#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <string.h>#include <pthread.h> #include <stdlib

32、.h>#include<sys/time.h>/*函數(shù)申明*/void writer_function(void);void serverThreadProc(void *);/鏈表結(jié)點(diǎn)結(jié)構(gòu)體typedef struct _CLIENT_INFO_charszClientIp16;int nClientPort;intnClientSock;struct_CLIENT_INFO_ *pNext;struct_CLIENT_INFO_ *pPre;CLIENT_INFO;/*數(shù)據(jù)類型*/typedef struct datatype unsigned char number;u

33、nsigned char age;unsigned char high;unsigned char weigh;long time;char *name;Datatype;/*協(xié)議包結(jié)構(gòu)*/typedef struct pro_packagechar head; /開始標(biāo)志為 設(shè)定為0x7E 1int lenth; /包的數(shù)據(jù)部分長(zhǎng)度 4unsigned char flag; /0 : cmd 1:data 1unsigned char stop; /0 stop 1:send 1unsigned char num; /標(biāo)明發(fā)送信息 1unsigned char data200; /數(shù)據(jù)部分

34、Pro_package;/*創(chuàng)建緩存區(qū)*/typedef struct queueDatatype buffer5; int b_tail;int b_head;queue; /*初始化隊(duì)列*/queue Queue = .b_tail = 0,.b_head = 0,;/*數(shù)據(jù)初始化*/char *NAME5 = "wuhao", "chenkai","liumenglin","liujin","liufeng"unsigned char AGE5 = 20,21,22,23,24;unsig

35、ned char NUM5 = 1,2,3,4,5;unsigned char HIGH5 = 175,174,173,175,165;unsigned char WIGHT5 = 58, 55, 62, 63, 50;Datatype information5;/*全局變量*/int nListenSock =-1; /server lisen socketint nThreadFlag =0; / thread start/stop flagCLIENT_INFO *pClientHead=NULL; /client list headerstruct timeval sys_time;p

36、thread_mutex_t mutex;int buffer_has_item=0;/主函數(shù)void main(void)/*子線程相關(guān)*/pthread_t reader = -1; /read進(jìn)程的進(jìn)程號(hào)pthread_mutex_init(&mutex,NULL); /初始化 互斥鎖/*初始化數(shù)據(jù)*/int i = 0;for(i=0; i<5; i+) = NAMEi;informationi.age = AGEi;informationi.number = NUMi;informationi.high = HIGHi;informat

37、ioni.weigh = WIGHTi; /*創(chuàng)建線程,產(chǎn)生數(shù)據(jù)*/pthread_create(&reader,NULL,(void*)&writer_function,NULL); /*主線程相關(guān)*/創(chuàng)建socketnListenSock =socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(nListenSock<0)printf("create listen socket errorn");return;/設(shè)置socket選項(xiàng)int nValue=1;if(setsockopt(nListenSock,SOL_

38、SOCKET,SO_REUSEADDR,(char*)&nValue,sizeof(int)<0)printf("set option SO_REUSEADDR fail!n");close(nListenSock);return;/綁定struct sockaddr_in localAddr;memset(&localAddr,0x0,sizeof(localAddr);localAddr.sin_family =AF_INET;localAddr.sin_addr.s_addr =htonl(INADDR_ANY);localAddr.sin_po

39、rt =htons(10000);if(bind(nListenSock,(struct sockaddr*)&localAddr,sizeof(struct sockaddr)<0)printf("bind liste sock fail!n");close(nListenSock);return;/監(jiān)聽if(listen(nListenSock,5)<0)printf("listen error!n");close(nListenSock);return;/創(chuàng)建客戶端的線程int nSrvThreadId =1;nThreadFl

40、ag =1;if(pthread_create(pthread_t*)&nSrvThreadId,NULL,(void*)&serverThreadProc,NULL)<0)printf("create server thread fail!n");close(nListenSock);return;/等待退出while(1)if(pthread_join(nSrvThreadId,NULL)!=0)return;/*處理客戶端函數(shù)*/void serverThreadProc(void *pPram)int nMaxFd;fd_set rset,al

41、lset;struct timeval timeOut=0,20*1000;FD_ZERO(&allset);FD_SET(nListenSock,&allset);nMaxFd =nListenSock;CLIENT_INFO *pTcpClient;int nSelectR;struct sockaddr_in clientAddr;CLIENT_INFO *pTempClient;unsigned char ucRcvBuf100;int nAddrSize =sizeof(clientAddr);Pro_package package; /定義包結(jié)構(gòu)unsigned c

42、har send_buffer200; /發(fā)送緩存int verify_flag = 0;while(1) /while 循環(huán)rset =allset;nSelectR =select(nMaxFd+1,&rset,NULL,NULL,&timeOut);if(nSelectR=-1) /若發(fā)生錯(cuò)誤continue;else if(nSelectR=0) /超時(shí)continue; if(FD_ISSET(nListenSock,&rset) / 檢查nListenSock是否在套接字集合中printf("accept client!n");int n

43、ConnectSock =accept(nListenSock,(struct sockaddr*)&clientAddr,&nAddrSize);if(nConnectSock=-1)printf("nConnectSock -1n");continue;/保存客戶端的信息pTcpClient =(CLIENT_INFO*)malloc(sizeof(CLIENT_INFO);pTcpClient->nClientSock =nConnectSock;pTcpClient->nClientPort =ntohs(clientAddr.sin_p

44、ort);strcpy(pTcpClient->szClientIp,inet_ntoa(clientAddr.sin_addr);pTcpClient->pNext =NULL;pTcpClient->pPre =NULL;printf("client connected,ip:%s,port:%dn",pTcpClient->szClientIp,pTcpClient->nClientPort);if(pClientHead=NULL)pClientHead= pTcpClient;elsepTempClient =pClientHead;

45、while(pTempClient->pNext!=NULL)pTempClient =pTempClient->pNext;pTempClient->pNext =pTcpClient;pTcpClient->pPre =pTempClient;/update fd setFD_SET(nConnectSock,&allset);if(nConnectSock>nMaxFd)nMaxFd =nConnectSock;else /對(duì)客戶端的服務(wù)/find the client pTcpClient =pClientHead;while(pTcpClient

46、!=NULL)int nRcvSock =pTcpClient->nClientSock;if(FD_ISSET(nRcvSock,&rset)=0)pTcpClient =pTcpClient->pNext;continue; /從客戶端接收數(shù)據(jù),需要修改int nLen =recv(nRcvSock,ucRcvBuf,sizeof(ucRcvBuf),MSG_NOSIGNAL);if(nLen<=0) /如果接收數(shù)據(jù)失敗/client disconnectedif(nRcvSock!=-1)shutdown(nRcvSock,SHUT_RDWR);close(nR

47、cvSock);pTcpClient->nClientSock =-1;/del this client infoFD_CLR(nRcvSock,&allset);printf("client disconnected,ip:%s,port:%dn",pTcpClient->szClientIp,pTcpClient->nClientPort);/del the client from listif(pTcpClient->pPre!=NULL)pTcpClient->pPre->pNext =pTcpClient->pNe

48、xt;elsepClientHead =pTcpClient->pNext;if(pTcpClient->pNext!=NULL)pTcpClient->pNext->pPre =pTcpClient->pPre;/freefree(pTcpClient);else /對(duì)客戶端請(qǐng)求進(jìn)行組包int i;for(i=0; i<nLen; i+) /尋找包頭if(ucRcvBufi = 0x7E)verify_flag = 1;break;if(verify_flag = 1)/*組包*/package.head = ucRcvBufi;memcpy(&p

49、ackage.lenth, &ucRcvBufi+1, 4); package.flag = ucRcvBufi+5;package.stop = ucRcvBufi+6;package.num = ucRcvBufi+7;/不需要數(shù)據(jù)i = 0; /i清0int g;if(package.flag = 0) int k=0;/查找數(shù)據(jù),組包for(k=0;k<5;k+) if(Queue.bufferk.number = package.num)/如果數(shù)字匹配 int sen_long = 8+8+strlen(Q); /包總長(zhǎng)度/包頭部分se

50、nd_buffer0 = package.head;memcpy(&send_buffer1, &sen_long, 4); /頭部為8個(gè)字節(jié)send_buffer5 = 1; /datasend_buffer6 = package.stop;send_buffer7 = package.num;/數(shù)據(jù)部分send_buffer8 = Queue.bufferk.number;send_buffer9 = Queue.bufferk.age;send_buffer10 = Queue.bufferk.high;send_buffer11 = Queue.bufferk.weigh;memcpy(&send_buffer12, &Queue.bufferk.time, 4); memcpy(&send_buffer16,Q,strlen(

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論