《通信嵌入式系統(tǒng)技術(shù)與應(yīng)用》 課件 第5講 多線程程序設(shè)計_第1頁
《通信嵌入式系統(tǒng)技術(shù)與應(yīng)用》 課件 第5講 多線程程序設(shè)計_第2頁
《通信嵌入式系統(tǒng)技術(shù)與應(yīng)用》 課件 第5講 多線程程序設(shè)計_第3頁
《通信嵌入式系統(tǒng)技術(shù)與應(yīng)用》 課件 第5講 多線程程序設(shè)計_第4頁
《通信嵌入式系統(tǒng)技術(shù)與應(yīng)用》 課件 第5講 多線程程序設(shè)計_第5頁
已閱讀5頁,還剩49頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

《通信嵌入式系統(tǒng)技術(shù)

與應(yīng)用》第五講五多線程程序設(shè)計1.Linux下線程概述 2.線程實現(xiàn) 1、Linux下線程概述

(1)線程概述

(2)線程分類

(3)Linux線程技術(shù)的發(fā)展1、Linux下線程概述(1)線程概述前面已經(jīng)提到,進程是系統(tǒng)中程序執(zhí)行和資源分配的基本單位。每個進程都擁有自己的數(shù)據(jù)段、代碼段和堆棧段,這就造成了進程在進行切換等操作時都需要有比較負責(zé)的上下文切換等動作。為了進一步減少處理機的空轉(zhuǎn)時間支持多處理器和減少上下文切換開銷,進程在演化中出現(xiàn)了另一個概念——線程。它是一個進程內(nèi)的基本調(diào)度單位,也可以稱為輕量級進程。線程是在共享內(nèi)存空間中并發(fā)的多道執(zhí)行路徑,它們共享一個進程的資源,如文件描述和信號處理。因此,大大減少了上下文切換的開銷。同進程一樣,線程也將相關(guān)的變量值放在線程控制表內(nèi)。一個進程可以有多個線程,也就是有多個線程控制表及堆棧寄存器,但卻共享一個用戶地址空間。要注意的是,由于線程共享了進程的資源和地址空間,因此,任何線程對系統(tǒng)資源的操作都會給其他線程帶來影響,因此,多線程中的同步就是非常重要的問題了。在多線程系統(tǒng)中,進程與進程的關(guān)系如表所示。1、Linux下線程概述進程用戶地址空間線程一線程二線程三1、Linux下線程概述(2)線程分類線程按照其調(diào)度者可以分為用戶級線程和核心級線程兩種。①用戶級線程用戶級線程主要解決的是上下文切換的問題,它的調(diào)度算法和調(diào)度過程全部由用戶自行選擇決定,在運行時不需要特定的內(nèi)核支持。在這里,操作系統(tǒng)往往會提供一個用戶空間的線程庫,該線程庫提供了線程的創(chuàng)建、調(diào)度、撤銷等功能,而內(nèi)核仍然僅對進程進行管理。如果一個進程中的某一個線程調(diào)用了一個阻塞的系統(tǒng)調(diào)用,那么該進程包括該進程中的其他所有線程也同時被阻塞。這種用戶級線程的主要缺點是在一個進程中的多個線程的調(diào)度中無法發(fā)揮多處理器的優(yōu)勢。1、Linux下線程概述②核心級線程這種線程允許不同進程中的線程按照同一相對優(yōu)先調(diào)度方法進行調(diào)度,這樣就可以發(fā)揮多處理器的并發(fā)優(yōu)勢。現(xiàn)在大多數(shù)系統(tǒng)都采用用戶級線程與核心級線程并存的方法。一個用戶級線程可以對應(yīng)一個或幾個核心級線程,也就是“一對一”或“多對一”模型。這樣既可滿足多處理機系統(tǒng)的需要,也可以最大限度地減少調(diào)度開銷。1、Linux下線程概述(3)Linux線程技術(shù)的發(fā)展在Linux中,線程技術(shù)也經(jīng)過了一代代的發(fā)展過程。在Linux2.2內(nèi)核中,并不存在真正意義上的線程。當(dāng)時Linux中常用的線程pthread實際上是通過進程來模擬的,也就是說Linux中的線程也是通過fork創(chuàng)建的“輕”進程,并且線程的個數(shù)也很有限,最多只能有4096個進程/線程同時運行。Linux2.4內(nèi)核消除了這個線程個數(shù)的限制,并且允許在系統(tǒng)運行中動態(tài)地調(diào)整進程數(shù)上限。當(dāng)時采用的是LinuxThread線程庫,它對應(yīng)的線程模型是“一對一”線程模型,也就是一個用戶級線程對應(yīng)一個內(nèi)核線程,而線程之間的管理在內(nèi)核外函數(shù)庫中實現(xiàn)。這種線程模型得到了廣泛應(yīng)用。但是,LinuxThread也由于Linux內(nèi)核的限制以及實現(xiàn)難度等原因,并不是完全與POSIX兼容。另外,它的進程ID、信號處理、線程總數(shù)、同步等各方面都還有諸多的問題。1、Linux下線程概述為了解決以上問題,在Linux2.6內(nèi)核中,進程調(diào)度通過重新編寫,刪除了以前版本中效率不高的算法。內(nèi)核線程框架也被重新編寫,開始使用NPTL(NativePOSIXThreadLibrary)線程庫。這個線程庫有以下幾點設(shè)計目標(biāo):POSIX兼容性、多處理器結(jié)構(gòu)的應(yīng)用、低啟動開銷、低鏈接開銷、與LinuxThreads應(yīng)用的二進制兼容性、軟硬件的可擴展能力、與C++集成等。這一切都使得Linux2.6內(nèi)核的線程機制更加完備,能夠更好地完成其設(shè)計目標(biāo)。與LinuxThreads不同,NPTL沒有使用管理線程,核心線程的管理直接放在核內(nèi)進行,這也帶了性能的優(yōu)化。由于NPTL仍然采用1:1的線程模型,NPTL仍然不是POSIX完全兼容的,但就性能而言相對LinuxThreads已經(jīng)有很大程度上的改進。2.線程實現(xiàn)(1)線程基本操作(2)線程訪問控制2.線程實現(xiàn)(1)線程基本操作這里要講的線程相關(guān)操作都是用戶空間線程的操作。在Linux中,一般Pthread線程庫是一套通用的線程庫,是由POSIX提出的,因此具有很好的可移植性2.線程實現(xiàn)<1>線程創(chuàng)建和退出創(chuàng)建線程實際上就是確定調(diào)用該線程函數(shù)的入口點,這里通常使用的函數(shù)是pthread_create。在線程創(chuàng)建以后,就開始運行相關(guān)的線程函數(shù),在該函數(shù)運行完之后,該線程也就退出了,這也是線程退出一種方法。另一種退出線程的方法是使用函數(shù)pthread_exit,這是線程的主動行為。這里要注意的是,在使用線程函數(shù)時,不能隨意使用exit退出函數(shù)進行出錯處理,由于exit的作用是使調(diào)用進程終止,往往一個進程包含多個線程,因此,在使用exit之后,該進程中的所有線程都終止了。因此,在線程中就可以使用pthread_exit來代替進程中的exit。由于一個進程中的多個線程是共享數(shù)據(jù)段的,因此通常在線程退出之后,退出線程所占用的資源并不會隨著線程的終止而得到釋放。正如進程之間可以用wait()系統(tǒng)調(diào)用來同步終止并釋放資源一樣,線程之間也有類似機制,那就是pthread_join()函數(shù)。pthread_join可以用于將當(dāng)前線程掛起,等待線程的結(jié)束。這個函數(shù)是一個線程阻塞的函數(shù),調(diào)用它的函數(shù)將一直等待到被等待的線程結(jié)束為止,當(dāng)函數(shù)返回時,被等待線程的資源就被收回。2.線程實現(xiàn)<2>修改線程屬性大家是否還記得pthread_create函數(shù)的第二個參數(shù)——線程的屬性。在上一個實例中,將該值設(shè)為NULL,也就是采用默認屬性,線程的多項屬性都是可以更改的。這些屬性主要包括綁定屬性、分離屬性、堆棧地址、堆棧大小、優(yōu)先級。其中系統(tǒng)默認的屬性為非綁定、非分離、缺省1M的堆棧、與父進程同樣級別的優(yōu)先級。下面首先對綁定屬性和分離屬性的基本概念進行講解。2.線程實現(xiàn)①綁定屬性前面已經(jīng)提到,Linux中采用“一對一”的線程機制,也就是一個用戶線程對應(yīng)一個內(nèi)核線程。綁定屬性就是指一個用戶線程固定地分配給一個內(nèi)核線程,因為CPU時間片的調(diào)度是面向內(nèi)核線程(也就是輕量級進程)的,因此具有綁定屬性的線程可以保證在需要的時候總有一個內(nèi)核線程與之對應(yīng)。而與之相對的非綁定屬性就是指用戶線程和內(nèi)核線程的關(guān)系不是始終固定的,而是由系統(tǒng)來控制分配的。2.線程實現(xiàn)②分離屬性分離屬性是用來決定一個線程以什么樣的方式來終止自己。在非分離情況下,當(dāng)一個線程結(jié)束時,它所占用的系統(tǒng)資源并沒有被釋放,也就是沒有真正的終止。只有當(dāng)pthread_join()函數(shù)返回時,創(chuàng)建的線程才能釋放自己占用的系統(tǒng)資源。而在分離屬性情況下,一個線程結(jié)束時立即釋放它所占有的系統(tǒng)資源。這里要注意的一點是,如果設(shè)置一個線程的分離屬性,而這個線程運行又非???,那么它很可能在pthread_create函數(shù)返回之前就終止了,它終止以后就可能將線程號和系統(tǒng)資源移交給其他的線程使用,這時調(diào)用pthread_create的線程就得到了錯誤的線程號。這些屬性的設(shè)置都是通過一定的函數(shù)來完成的,通常首先調(diào)用pthread_attr_init函數(shù)進行初始化,之后再調(diào)用相應(yīng)的屬性設(shè)置函數(shù)。設(shè)置綁定屬性的函數(shù)為pthread_attr_setscope,設(shè)置線程分離屬性的函數(shù)為pthread_attr_setdetachstate,設(shè)置線程優(yōu)先級的相關(guān)函數(shù)為pthread_attr_getschedparam(獲取線程優(yōu)先級)和pthread_attr_setschedparam(設(shè)置線程優(yōu)先級)。在設(shè)置完這些屬性后,就可以調(diào)用pthread_create函數(shù)來創(chuàng)建線程了。2.線程實現(xiàn)(2)線程訪問控制由于線程共享進程的資源和地址空間,因此在對這些資源進行操作時,必須考慮到線程間資源訪問的惟一性問題,這里主要介紹POSIX中線程同步的方法,主要有互斥鎖和信號量的方式。2.線程實現(xiàn)<1>mutex互斥鎖線程控制mutex是一種簡單的加鎖的方法來控制對共享資源的存取。這個互斥鎖只有兩種狀態(tài),也就是上鎖和解鎖,可以把互斥鎖看作某種意義上的全局變量。在同一時刻只能有一個線程掌握某個互斥上的鎖,擁有上鎖狀態(tài)的線程能夠?qū)蚕碣Y源進行操作。若其他線程希望上鎖一個已經(jīng)上鎖了的互斥鎖,則該線程就會掛起,直到上鎖的線程釋放掉互斥鎖為止。可以說,這把互斥鎖使得共享資源按序在各個線程中操作。互斥鎖的操作主要包括以下幾個步驟:互斥鎖初始化:pthread_mutex_init互斥鎖上鎖:pthread_mutex_lock互斥鎖判斷上鎖:pthread_mutex_trylock互斥鎖接鎖:pthread_mutex_unlock消除互斥鎖:pthread_mutex_destroy其中,互斥鎖可以分為快速互斥鎖、遞歸互斥鎖和檢錯互斥鎖。這三種鎖的區(qū)別主要在于其他未占有互斥鎖的線程在希望得到互斥鎖時的是否需要阻塞等待??焖冁i是指調(diào)用線程會阻塞直至擁有互斥鎖的線程解鎖為止。遞歸互斥鎖能夠成功地返回并且增加調(diào)用線程在互斥上加鎖的次數(shù),而檢錯互斥鎖則為快速互斥鎖的非阻塞版本,它會立即返回并返回一個錯誤信息。2.線程實現(xiàn)<2>信號量線程控制在前面中已經(jīng)講到,信號量也就是操作系統(tǒng)中所用到的PV原語,它廣泛用于進程或線程間的同步與互斥。信號量本質(zhì)上是一個非負的整數(shù)計數(shù)器,它被用來控制對公共資源的訪問。這里先來簡單復(fù)習(xí)一下PV原語的工作原理。PV原語是對整數(shù)計數(shù)器信號量sem的操作。一次P操作使sem減一,而一次V操作使sem加一。進程(或線程)根據(jù)信號量的值來判斷是否對公共資源具有訪問權(quán)限。當(dāng)信號量sem的值大于等于零時,該進程(或線程)具有公共資源的訪問權(quán)限;相反,當(dāng)信號量sem的值小于零時,該進程(或線程)就將阻塞直到信號量sem的值大于等于0為止。2.線程實現(xiàn)PV原語主要用于進程或線程間的同步和互斥這兩種典型情況。若用于互斥,幾個進程(或線程)往往只設(shè)置一個信號量sem,它們的操作流程如圖所示。初始化信號量為1開始P操作線程一執(zhí)行V操作P操作線程二執(zhí)行V操作結(jié)束2.線程實現(xiàn)當(dāng)信號量用于同步操作時,往往會設(shè)置多個信號量,并安排不同的初始值來實現(xiàn)它們之間的順序執(zhí)行,它們的操作流程如圖所示。初始化信號量sem1為1,sem2為0開始P操作sem1線程一執(zhí)行V操作sem2P操作sem2線程二執(zhí)行V操作sem1結(jié)束六.嵌入式網(wǎng)絡(luò)程序設(shè)計1.TCP/IP協(xié)議概述 2.網(wǎng)絡(luò)基礎(chǔ)編程 3.網(wǎng)絡(luò)高級編程 4.ping源碼分析1.TCP/IP協(xié)議概述

(1)OSI參考模型及TCP/IP參考模型(2)TCP/IP協(xié)議族(3)TCP和UDP1.TCP/IP協(xié)議概述

(1)OSI參考模型及TCP/IP參考模型大家一定都聽說過著名的OSI協(xié)議參考模型,它是基于國際標(biāo)準(zhǔn)化組織(ISO)的建議發(fā)展起來的,從上到下共分為7層:應(yīng)用層、表示層、會話層、傳輸層、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層及物理層。這個7層的協(xié)議模型雖然規(guī)定得非常細致和完善,但在實際中卻得不到廣泛的應(yīng)用,其重要的原因之一就在于它過于復(fù)雜。但它仍是此后很多協(xié)議模型的基礎(chǔ),這種分層架構(gòu)的思想在很多領(lǐng)域都得到了廣泛的應(yīng)用。1.TCP/IP協(xié)議概述與此相區(qū)別的TCP/IP協(xié)議模型從一開始就遵循簡單明確的設(shè)計思路,它將TCP/IP的7層協(xié)議模型簡化為4層,從而更有利于實現(xiàn)和使用。TCP/IP的協(xié)議參考模型和OSI協(xié)議參考模型的對應(yīng)關(guān)系如下圖所示。應(yīng)用層表示層會話層傳輸層網(wǎng)絡(luò)層數(shù)據(jù)鏈路層物理層傳輸層網(wǎng)絡(luò)層網(wǎng)絡(luò)接口層應(yīng)用層OSI參考模型TCP/IP參考模型1.TCP/IP協(xié)議概述下面分別對者TCP/IP的4層模型進行簡要介紹。網(wǎng)絡(luò)接口層:負責(zé)將二進制流轉(zhuǎn)換為數(shù)據(jù)幀,并進行數(shù)據(jù)幀的發(fā)送和接收。要注意的是數(shù)據(jù)幀是獨立的網(wǎng)絡(luò)信息傳輸單元。網(wǎng)絡(luò)層:負責(zé)將數(shù)據(jù)幀封裝成IP數(shù)據(jù)報,并運行必要的路由算法。傳輸層:負責(zé)端對端之間的通信會話連接與建立。傳輸協(xié)議的選擇根據(jù)數(shù)據(jù)傳輸方式而定。應(yīng)用層:負責(zé)應(yīng)用程序的網(wǎng)絡(luò)訪問,這里通過端口號來識別各個不同的進程。1.TCP/IP協(xié)議概述(2)TCP/IP協(xié)議族雖然TCP/IP名稱只包含了兩個協(xié)議,但實際上,TCP/IP是一個龐大的協(xié)議族,它包括了各個層次上的眾多協(xié)議,下圖列舉了各層中一些重要的協(xié)議,并給出了各個協(xié)議在不同層次中所處的位置。telnetftpTCPUDPICMPIGMPIPv4IPv6ARPRARPMPLS應(yīng)用層傳輸層網(wǎng)絡(luò)層網(wǎng)絡(luò)接口層1.TCP/IP協(xié)議概述ARP:用于獲得同一物理網(wǎng)絡(luò)中的硬件主機地址。MPLS:多協(xié)議標(biāo)簽協(xié)議,是很有發(fā)展前景的下一代網(wǎng)絡(luò)協(xié)議。IP:負責(zé)在主機和網(wǎng)絡(luò)之間尋址和路由數(shù)據(jù)包。ICMP:用于發(fā)送報告有關(guān)數(shù)據(jù)包的傳送錯誤的協(xié)議。IGMP:被IP主機用來向本地多路廣播路由器報告主機組成員的協(xié)議。TCP:為應(yīng)用程序提供可靠的通信連接。適合于一次傳輸大批數(shù)據(jù)的情況。并適用于要求得到響應(yīng)的應(yīng)用程序。UDP:提供了無連接通信,且不對傳送包進行可靠的保證。適合于一次傳輸少量數(shù)據(jù),可靠性則由應(yīng)用層來負責(zé)。1.TCP/IP協(xié)議概述(3)TCP和UDP在此主要介紹在網(wǎng)絡(luò)編程中涉及到的傳輸層TCP和UDP協(xié)議。1.TCP/IP協(xié)議概述<1>TCP※概述同其他任何協(xié)議棧一樣,TCP向相鄰的高層提供服務(wù)。因為TCP的上一層就是應(yīng)用層,因此,TCP數(shù)據(jù)傳輸實現(xiàn)了從一個應(yīng)用程序到另一個應(yīng)用程序的數(shù)據(jù)傳遞。應(yīng)用程序通過編程調(diào)用TCP并使用TCP服務(wù),提供需要準(zhǔn)備發(fā)送的數(shù)據(jù),用來區(qū)分接收數(shù)據(jù)應(yīng)用的目的地址和端口號。通常應(yīng)用程序通過打開一個socket來使用TCP服務(wù),TCP管理到其他socket的數(shù)據(jù)傳遞。可以說,通過IP的源/目的可以惟一地區(qū)分網(wǎng)絡(luò)中兩個設(shè)備的關(guān)聯(lián),通過socket的源/目的可以惟一地區(qū)分網(wǎng)絡(luò)中兩個應(yīng)用程序的關(guān)聯(lián)。1.TCP/IP協(xié)議概述※三次握手協(xié)議TCP對話通過三次握手來初始化的。三次握手的目的是使數(shù)據(jù)段的發(fā)送和接收同步,告訴其他主機其一次可接收的數(shù)據(jù)量,并建立虛連接。下面描述了這三次握手的簡單過程:初始化主機通過一個同步標(biāo)志置位的數(shù)據(jù)段發(fā)出會話請求。接收主機通過發(fā)回具有以下項目的數(shù)據(jù)段表示回復(fù):同步標(biāo)志置位、即將發(fā)送的數(shù)據(jù)段的起始字節(jié)的順序號、應(yīng)答并帶有將收到的下一個數(shù)據(jù)段的字節(jié)順序號。請求主機再回送一個數(shù)據(jù)段,并帶有確認順序號和確認號。1.TCP/IP協(xié)議概述下圖就是這個流程的簡單示意圖:TCP實體所采用的基本協(xié)議是滑動窗口協(xié)議。當(dāng)發(fā)送方傳送一個數(shù)據(jù)報時,它將啟動計時器。當(dāng)該數(shù)據(jù)報到達目的地后,接收方的TCP實體向回發(fā)送一個數(shù)據(jù)報,其中包含有一個確認序號,它意思是希望收到的下一個數(shù)據(jù)報的順序號。如果發(fā)送方的定時器在確認信息到達之前超時,那么發(fā)送方會重發(fā)該數(shù)據(jù)報。SYNJSYNK,ACKJ+1ACKK+11.TCP/IP協(xié)議概述※TCP數(shù)據(jù)報頭下圖給出了TCP數(shù)據(jù)報頭的格式。1.TCP/IP協(xié)議概述TCP數(shù)據(jù)報頭的含義如下所示:源端口、目的端口:16位長。標(biāo)識出遠端和本地的端口號。序號:32位長。標(biāo)識發(fā)送的數(shù)據(jù)報的順序。確認號:32位長。希望收到的下一個數(shù)據(jù)報的序列號。TCP頭長:4位長。表明TCP頭中包含多少個32位字。6位未用。ACK:ACK位置1表明確認號是合法的。如果ACK為0,那么數(shù)據(jù)報不包含確認信息,確認字段被省略。PSH:表示是帶有PUSH標(biāo)志的數(shù)據(jù)。接收方因此請求數(shù)據(jù)報一到便可送往應(yīng)用程序而不必等到緩沖區(qū)裝滿時才傳送。RST:用于復(fù)位由于主機崩潰或其他原因而出現(xiàn)的錯誤的連接。還可以用于拒絕非法的數(shù)據(jù)報或拒絕連接請求。SYN:用于建立連接。FIN:用于釋放連接。窗口大?。?6位長。窗口大小字段表示在確認了字節(jié)之后還可以發(fā)送多少個字節(jié)。校驗和:16位長。是為了確保高可靠性而設(shè)置。它校驗頭部、數(shù)據(jù)和偽TCP頭部之和??蛇x項:0個或多個32位字。包括最大TCP載荷,窗口比例、選擇重發(fā)數(shù)據(jù)報等選項。1.TCP/IP協(xié)議概述<2>UDP※概述UDP即用戶數(shù)據(jù)報協(xié)議,它是一種無連接協(xié)議,因此不需要像TCP那樣通過三次握手來建立一個連接。同時,一個UDP應(yīng)用可同時作為應(yīng)用的客戶或服務(wù)器方。由于UDP協(xié)議并不需要建立一個明確的連接,因此建立UDP應(yīng)用要比建立TCP應(yīng)用簡單得多。UDP協(xié)議從問世至今已經(jīng)被使用了很多年,雖然其最初的光彩已經(jīng)被一些類似協(xié)議所掩蓋,但是在網(wǎng)絡(luò)質(zhì)量越來越高的今天,UDP的應(yīng)用得到了大大的增強。它比TCP協(xié)議更為高效,也能更好地解決實時性的問題。如今,包括網(wǎng)絡(luò)視頻會議系統(tǒng)在內(nèi)的眾多的客戶/服務(wù)器模式的網(wǎng)絡(luò)應(yīng)用都使用UDP協(xié)議1.TCP/IP協(xié)議概述※UDP數(shù)據(jù)包頭UDP數(shù)據(jù)包頭如下圖所示。源地址、目的地址:16位長。標(biāo)識出遠端和本地的端口號。數(shù)據(jù)報的長度是指包括報頭和數(shù)據(jù)部分在內(nèi)的總的字節(jié)數(shù)。因為報頭的長度是固定的,所以該域主要用來計算可變長度的數(shù)據(jù)部分(又稱為數(shù)據(jù)負載)。源地址目的地址0協(xié)議UDP長度07815162324311.TCP/IP協(xié)議概述<3>協(xié)議的選擇協(xié)議的選擇應(yīng)該考慮到以下3個方面:<1>對數(shù)據(jù)可靠性的要求對數(shù)據(jù)要求高可靠性的應(yīng)用需選擇TCP協(xié)議,如驗證、密碼字段的傳送都是不允許出錯的,而對數(shù)據(jù)的可靠性要求不那么高的應(yīng)用可選擇UDP傳送。<2>應(yīng)用的實時性由于TCP協(xié)議在傳送過程中要進行三次握手、重傳確認等手段來保證數(shù)據(jù)傳輸?shù)目煽啃?。使用TCP協(xié)議會有較大的時延,因此不適合對實時性要求較高的應(yīng)用,如VOIP、視頻監(jiān)控等。相反,UDP協(xié)議則在這些應(yīng)用中能發(fā)揮很好的作用。<3>網(wǎng)絡(luò)的可靠性由于TCP協(xié)議的提出主要是解決網(wǎng)絡(luò)的可靠性問題,它通過各種機制來減少錯誤發(fā)生的概率。因此,在網(wǎng)絡(luò)狀況不是很好的情況下需選用TCP協(xié)議(如在廣域網(wǎng)等情況),但是若在網(wǎng)絡(luò)狀況很好的情況下(如局域網(wǎng)等)就不需要再采用TCP協(xié)議,選擇UDP協(xié)議來減少網(wǎng)絡(luò)負荷。2.網(wǎng)絡(luò)基礎(chǔ)編程(1)socket概述(2)地址及順序處理(3)socket基礎(chǔ)編程2.網(wǎng)絡(luò)基礎(chǔ)編程(1)socket概述<1>socket定義在Linux中的網(wǎng)絡(luò)編程是通過socket接口來進行的。人們常說的socket接口是一種特殊的I/O,它也是一種文件描述符。每一個socket都用一個半相關(guān)描述{協(xié)議,本地地址、本地端口}來表示;一個完整的套接字則用一個相關(guān)描述{協(xié)議,本地地址、本地端口、遠程地址、遠程端口}。socket也有一個類似于打開文件的函數(shù)調(diào)用,該函數(shù)返回一個整型的socket描述符,隨后的連接建立、數(shù)據(jù)傳輸?shù)炔僮鞫际峭ㄟ^socket來實現(xiàn)的。2.網(wǎng)絡(luò)基礎(chǔ)編程<2>socket類型常見的socket有3種類型如下:<1>流式socket(SOCK_STREAM)流式套接字提供可靠的、面向連接的通信流;它使用TCP協(xié)議,從而保證了數(shù)據(jù)傳輸?shù)恼_性和順序性。<2>數(shù)據(jù)報socket(SOCK_DGRAM)數(shù)據(jù)報套接字定義了一種無連接的服務(wù),數(shù)據(jù)通過相互獨立的報文進行傳輸,是無序的,并且不保證是可靠、無差錯的。它使用數(shù)據(jù)報協(xié)議UDP。<3>原始socket原始套接字允許對底層協(xié)議如IP或ICMP進行直接訪問,它功能強大但使用較為不便,主要用于一些協(xié)議的開發(fā)。2.網(wǎng)絡(luò)基礎(chǔ)編程(2)地址及順序處理<1>地址結(jié)構(gòu)相關(guān)處理※數(shù)據(jù)結(jié)構(gòu)介紹下面首先介紹兩個重要的數(shù)據(jù)類型:sockaddr和sockaddr_in這兩個數(shù)據(jù)類型是等效的,可以相互轉(zhuǎn)化,通常sockaddr_in數(shù)據(jù)類型使用更為方便。在建立socketadd或sockaddr_in后,就可以對該socket進行適當(dāng)?shù)牟僮髁恕?.網(wǎng)絡(luò)基礎(chǔ)編程<2>數(shù)據(jù)存儲優(yōu)先順序※函數(shù)說明計算機數(shù)據(jù)存儲有兩種字節(jié)優(yōu)先順序:高位字節(jié)優(yōu)先和低位字節(jié)優(yōu)先。Internet上數(shù)據(jù)以高位字節(jié)優(yōu)先順序在網(wǎng)絡(luò)上傳輸,因此在有些情況下,需要對這兩個字節(jié)存儲優(yōu)先順序進行相互轉(zhuǎn)化。這里用到了四個函數(shù):htons、ntohs、htonl、ntohl。這四個地址分別實現(xiàn)網(wǎng)絡(luò)字節(jié)序和主機字節(jié)序的轉(zhuǎn)化,這里的h代表host,n代表network,s代表short,l代表long。通常16位的IP端口號用s代表,而IP地址用l來代表。2.網(wǎng)絡(luò)基礎(chǔ)編程<3>地址格式轉(zhuǎn)化※函數(shù)說明通常用戶在表達地址時采用的是點分十進制表示的數(shù)值(或者是以冒號分開的十進制IPv6地址),而在通常使用的socket編程中所使用的則是二進制值,這就需要將這兩個數(shù)值進行轉(zhuǎn)換。這里在IPv4中用到的函數(shù)有inet_aton、inet_addr和inet_ntoa,而IPv4和IPv6兼容的函數(shù)有inet_pton和inet_ntop。由于IPv6是下一代互聯(lián)網(wǎng)的標(biāo)準(zhǔn)協(xié)議,因此,本書講解的函數(shù)都能夠同時兼容IPv4和IPv6,但在具體舉例時仍以IPv4為例。這里inet_pton函數(shù)是將點分十進制地址映射為二進制地址,而inet_ntop是將二進制地址映射為點分十進制地址。2.網(wǎng)絡(luò)基礎(chǔ)編程<4>名字地址轉(zhuǎn)化※函數(shù)說明通常,人們在使用過程中都不愿意記憶冗長的IP地址,尤其到IPv6時,地址長度多達128位,那時就更加不可能一次次記憶那么長的IP地址了。因此,使用主機名將會是很好的選擇。在Linux中,同樣有一些函數(shù)可以實現(xiàn)主機名和地址的轉(zhuǎn)化,最為常見的有g(shù)ethostbyname、gethostbyaddr、getaddrinfo等,它們都可以實現(xiàn)IPv4和IPv6的地址和主機名之間的轉(zhuǎn)化。其中g(shù)ethostbyname是將主機名轉(zhuǎn)化為IP地址,gethostbyaddr則是逆操作,是將IP地址轉(zhuǎn)化為主機名,另外getaddrinfo還能實現(xiàn)自動識別IPv4地址和IPv6地址。2.網(wǎng)絡(luò)基礎(chǔ)編程(3)socket基礎(chǔ)編程函數(shù)說明進行socket編程的基本函數(shù)有socket、bind、listen、accept、send、sendto、recv、recvfrom這幾個,其中對于客戶端和服務(wù)器端以及TCP和UDP的操作流程都有所區(qū)別,這里先對每個函數(shù)進行一定的說明,再給出不同情況下使用的流程圖。socket:該函數(shù)用于建立一個socket連接,可指定socket類型等信息。在建立了socket連接之后,可對socketadd或sockaddr_in進行初始化,以保存所建立的socket信息。bind:該函數(shù)是用于將本地IP地址綁定端口號的,若綁定其他地址則不能成功。另外,它主要用于TCP的連接,而在UDP的連接中則無必要。connect:該函數(shù)在TCP中是用于bind的之后的client端,用于與服務(wù)器端建立連接,而在UDP中由于沒有了bind函數(shù),因此用connect有點類似bind函數(shù)的作用。send和recv:這兩個函數(shù)用于接收和發(fā)送數(shù)據(jù),可以用在TCP中,也可以用在UDP中。當(dāng)用在UDP時,可以在connect函數(shù)建立連接之后再用。sendto和recvfrom:這兩個函數(shù)的作用與send和recv函數(shù)類型,也可以用在TCP和UDP中。當(dāng)用在TCP時,后面的幾個與地址有關(guān)參數(shù)不起作用,函數(shù)作用等同于send和recv;當(dāng)用在UDP時,可以用在之前沒有使用connect的情況時,這兩個函數(shù)可以自動尋找制定地址并進行連接。2.網(wǎng)絡(luò)基礎(chǔ)編程服務(wù)器端和客戶端使用TCP協(xié)議的流程圖如圖所示。socket服務(wù)器端recv/recvfrombindlistenacceptsend/sendtoclosesocket客戶端send/sendtobindconnectrecv/recvfromclose2.網(wǎng)絡(luò)基礎(chǔ)編程服務(wù)器端和客戶端使用UDP協(xié)議的流程圖如下圖所示。socket服務(wù)器端recvbindlistenacceptsendclosesocket客戶端sendbindconnectrecvclosefecvfromsendtosendtorecvfrom////3.網(wǎng)絡(luò)高級編程在實際情況中,人們往往遇到多個客戶端連接服務(wù)器端的情況。由于之前介紹的如connet、recv、send都是阻塞性函數(shù),若資源沒有準(zhǔn)備好,則調(diào)用該函數(shù)的進程將進入睡眠狀態(tài),這樣就無法處理I/O多路復(fù)用的情況了。本節(jié)給出了兩種解決I/O多路復(fù)用的解決方法,這兩個函數(shù)都是之前學(xué)過的fcntl和select(請讀者先復(fù)習(xí)第6章中的相關(guān)內(nèi)容)??梢钥吹?,由于在Linux中把socket也作為一種特殊文件描述符,這給用戶的處理帶來了很大的方便。3.網(wǎng)絡(luò)高級編程(1)fcntl函數(shù)fcntl針對socket編程提供了如下的編程特性。非阻塞I/O:可將cmd設(shè)置為F_SETFL,將lock設(shè)置為O_NONBLOCK。信號驅(qū)動I/O:可將cmd設(shè)置為F_SETFL,將lock設(shè)置為O_ASYNC。3.網(wǎng)絡(luò)高級編程(2)select使用fcntl函數(shù)雖然可以實現(xiàn)非阻塞I/O或信號驅(qū)動I/O,但在實際使用時往往會對資源

溫馨提示

  • 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)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論