網(wǎng)絡(luò)編程面試

1.http://blog.csdn.net/fayery/article/details/38724915

1、TCP和UDP的區(qū)別:

1)TCP提供面向連接的傳輸,通信前要先建立連接(三次握手機制);UDP提供無連接的傳輸,通信前不需要建立連接。

2)TCP提供可靠的傳輸(有序,無差錯,不丟失,不重復(fù));UDP提供不可靠的傳輸。

3)TCP面向字節(jié)流的傳輸,因此它能將信息分割成組,并在接收端將其重組;UDP是面向數(shù)據(jù)報的傳輸,沒有分組開銷。

4)TCP提供擁塞控制和流量控制機制;UDP不提供擁塞控制和流量控制機制。

2、流量控制和擁塞控制的實現(xiàn)機制:

1)TCP采用大小可變的滑動窗口機制實現(xiàn)流量控制功能。窗口的大小是字節(jié)。在TCP報文段首部的窗口字段寫入的數(shù)值就是當(dāng)前給對方設(shè)置發(fā)送窗口的數(shù)據(jù)的上限。

在數(shù)據(jù)傳輸過程中,TCP提供了一種基于滑動窗口協(xié)議的流量控制機制,用接收端接收能力(緩沖區(qū)的容量)的大小來控制發(fā)送端發(fā)送的數(shù)據(jù)量。

2)采用滑動窗口機制還可對網(wǎng)絡(luò)進行擁塞控制,將網(wǎng)絡(luò)中的分組(TCP報文段作為其數(shù)據(jù)部分)數(shù)量維持在一定的數(shù)量之下,當(dāng)超過該數(shù)值時,網(wǎng)絡(luò)的性能會急劇惡化。傳輸層的擁塞控制有慢開始(Slow-Start)、擁塞避免(Congestion?Avoidance)、快重傳(Fast?Retransmit)和快恢復(fù)(Fast?Recovery)四種算法。

擁塞: 大量數(shù)據(jù)報涌入同一交換節(jié)點(如路由器),導(dǎo)致該節(jié)點資源耗盡而必須丟棄后面到達的數(shù)據(jù)報時,就是擁塞。

3、重傳機制:

TCP每發(fā)送一個報文段,就設(shè)置一次定時器。只要定時器設(shè)置的重發(fā)時間到而還沒有收到確認(rèn),就要重發(fā)這一報文段。

TCP環(huán)境

報文往返時間不定、有很大差別

A、B在一個局域網(wǎng)絡(luò),往返時延很小

A、C在一個互聯(lián)網(wǎng)內(nèi),往返時延很大

因此,A很難確定一個固定的、與B、C通信都適用的定時器時間

TCP采用了一種自適應(yīng)算法。這種算法記錄每一個報文段發(fā)出的時間,以及收到相應(yīng)的確認(rèn)報文段的時間。這兩個時間之差就是報文段的往返時延。將各個報文段的往返時延樣本加權(quán)平均,就得出報文段的平均往返時延T。4、滑動窗口機制:

TCP采用大小可變的滑動窗口進行流量控制。窗口大小的單位是字節(jié)。

在TCP報文段首部的窗口字段寫入的數(shù)值就是當(dāng)前給對方設(shè)置的發(fā)送窗口數(shù)值的上限。發(fā)送窗口在連接建立時由雙方商定。但在通信的過程中,接收端可根據(jù)自己的資源情況,隨時動態(tài)地調(diào)整對方的發(fā)送窗口上限值(可增大或減小)。

5、多線程如何同步:

臨界區(qū)、互斥區(qū)、事件、信號量四種方式

臨界區(qū)(Critical Section)、互斥量(Mutex)、信號量(Semaphore)、事件(Event)的區(qū)別

1)、臨界區(qū):通過對多線程的串行化來訪問公共資源或一段代碼,速度快,適合控制數(shù)據(jù)訪問。在任意時刻只允許一個線程對共享資源進行訪問,如果有多個線程試圖訪問公共資源,那么在有一個線程進入后,其他試圖訪問公共資源的線程將被掛起,并一直等到進入臨界區(qū)的線程離開,臨界區(qū)在被釋放后,其他線程才可以搶占。

2)、互斥量:采用互斥對象機制。 只有擁有互斥對象的線程才有訪問公共資源的權(quán)限,因為互斥對象只有一個,所以能保證公共資源不會同時被多個線程訪問?;コ獠粌H能實現(xiàn)同一應(yīng)用程序的公共資源安全共享,還能實現(xiàn)不同應(yīng)用程序的公共資源安全共享 .互斥量比臨界區(qū)復(fù)雜。因為使用互斥不僅僅能夠在同一應(yīng)用程序不同線程中實現(xiàn)資源的安全共享,而且可以在不同應(yīng)用程序的線程之間實現(xiàn)對資源的安全共享。

3)、信號量:它允許多個線程在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大線程數(shù)目 .信號量對象對線程的同步方式與前面幾種方法不同,信號允許多個線程同時使用共享資源,這與操作系統(tǒng)中的PV操作相同。它指出了同時訪問共享資源的線程最大數(shù)目。它允許多個線程在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大線程數(shù)目。

PV操作及信號量的概念都是由荷蘭科學(xué)家E.W.Dijkstra提出的。信號量S是一個整數(shù),S大于等于零時代表可供并發(fā)進程使用的資源實體數(shù),但S小于零時則表示正在等待使用共享資源的進程數(shù)。

P操作申請資源:

(1)S減1;

(2)若S減1后仍大于等于零,則進程繼續(xù)執(zhí)行;

(3)若S減1后小于零,則該進程被阻塞后進入與該信號相對應(yīng)的隊列中,然后轉(zhuǎn)入進程調(diào)度。

V操作 釋放資源:

(1)S加1;

(2)若相加結(jié)果大于零,則進程繼續(xù)執(zhí)行;

(3)若相加結(jié)果小于等于零,則從該信號的等待隊列中喚醒一個等待進程,然后再返回原進程繼續(xù)執(zhí)行或轉(zhuǎn)入進程調(diào)度。

4)、事 件: 通過通知操作的方式來保持線程的同步,還可以方便實現(xiàn)對多個線程的優(yōu)先級比較的操作 .

總結(jié):

1) 互斥量與臨界區(qū)的作用非常相似,但互斥量是可以命名的,也就是說它可以跨越進程使用。所以創(chuàng)建互斥量需要的資源更多,所以如果只為了在進程內(nèi)部是用的話使用臨界區(qū)會帶來速度上的優(yōu)勢并能夠減少資源占用量。因為互斥量是跨進程的互斥量一旦被創(chuàng)建,就可以通過名字打開它。

2) 互斥量(Mutex),信號燈(Semaphore),事件(Event)都可以被跨越進程使用來進行同步數(shù)據(jù)操作,而其他的對象與數(shù)據(jù)同步操作無關(guān),但對于進程和線程來講,如果進程和線程在運行狀態(tài)則為無信號狀態(tài),在退出后為有信號狀態(tài)。所以可以使用WaitForSingleObject來等待進程和線程退出。

3) 通過互斥量可以指定資源被獨占的方式使用,但如果有下面一種情況通過互斥量就無法處理,比如現(xiàn)在一位用戶購買了一份三個并發(fā)訪問許可的數(shù)據(jù)庫系統(tǒng),可以根據(jù)用戶購買的訪問許可數(shù)量來決定有多少個線程/進程能同時進行數(shù)據(jù)庫操作,這時候如果利用互斥量就沒有辦法完成這個要求,信號燈對象可以說是一種資源計數(shù)器。

6、進程和線程的區(qū)別:

答:線程是指進程內(nèi)的一個執(zhí)行單元,也是進程內(nèi)的可調(diào)度實體。與進程的區(qū)別:

(1)調(diào)度:進程作為擁有資源的基本單位,線程作為調(diào)度和分配的基本單位;

(2)并發(fā)性:不僅進程之間可以并發(fā)執(zhí)行,同一個進程的多個線程之間也可并發(fā)執(zhí)行。

(3)擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統(tǒng)資源,但可以訪問隸屬于進程的資源.

(4)系統(tǒng)開銷:在創(chuàng)建或撤消進程時,由于系統(tǒng)都要為之分配和回收資源,導(dǎo)致系統(tǒng)的開銷明顯大于創(chuàng)建或撤消線程時的開銷。

7、進程間通訊的方式有哪些,各有什么優(yōu)缺點:

1)管道:管道是一種半雙工的通信方式,數(shù)據(jù)只能單向流動,而且只能在具有親緣關(guān)系的進程之間使用。進程的親緣關(guān)系通常是指父子進程關(guān)系。

2)有名管道(FIFO):有名管道也是半雙工的通信方式,但是允許在沒有親緣關(guān)系的進程之間使用,管道是先進先出的通信方式。

3)信號量:信號量是一個計數(shù)器,可以用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內(nèi)不同線程之間的同步手段。

4)消息隊列:消息隊列是有消息的鏈表,存放在內(nèi)核中并由消息隊列標(biāo)識符標(biāo)識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點。

5)信號 ( sinal ) :信號是一種比較復(fù)雜的通信方式,用于通知接收進程某個事件已經(jīng)發(fā)生。

6)共享內(nèi)存( shared memory ) :共享內(nèi)存就是映射一段能被其他進程所訪問的內(nèi)存,這段共享內(nèi)存由一個進程創(chuàng)建,但多個進程都可以訪問。共享內(nèi)存是最快的 IPC 方式,它是針對其他進程間通信方式運行效率低而專門設(shè)計的。它往往與其他通信機制,如信號量,配合使用,來實現(xiàn)進程間的同步和通信。

7)套接字( socket ) :套接字也是一種進程間通信機制,與其他通信機制不同的是,它可用于不同機器間的進程通信

8、tcp連接建立的時候3次握手的具體過程,以及每一步原因:

(1)????第一步:源主機A的TCP向主機B發(fā)出連接請求報文段,其首部中的SYN(同步)標(biāo)志位應(yīng)置為1,表示想與目標(biāo)主機B進行通信,并發(fā)送一個同步序列號X(例:SEQ=100)進行同步,表明在后面?zhèn)魉蛿?shù)據(jù)時的第一個數(shù)據(jù)字節(jié)的序號是X+1(即101)。SYN同步報文會指明客戶端使用的端口以及TCP連接的初始序號。

(2)  第二步:目標(biāo)主機B的TCP收到連接請求報文段后,如同意,則發(fā)回確認(rèn)。在確認(rèn)報中應(yīng)將ACK位和SYN位置1,表示客戶端的請求被接受。確認(rèn)號應(yīng)為X+1(圖中為101),同時也為自己選擇一個序號Y。

(3)  第三步:源主機A的TCP收到目標(biāo)主機B的確認(rèn)后要向目標(biāo)主機B給出確認(rèn)其ACK置1,確認(rèn)號為Y+1,而自己的序號為X+1。TCP的標(biāo)準(zhǔn)規(guī)定,SYN置1的報文段要消耗掉一個序號。

運行客戶進程的源主機A的TCP通知上層應(yīng)用進程,連接已經(jīng)建立。當(dāng)源主機A向目標(biāo)主機B發(fā)送第一個數(shù)據(jù)報文段時,其序號仍為X+1,因為前一個確認(rèn)報文段并不消耗序號。

當(dāng)運行服務(wù)進程的目標(biāo)主機B的TCP收到源主機A的確認(rèn)后,也通知其上層應(yīng)用進程,連接已經(jīng)建立。至此建立了一個全雙工的連接。

9、tcp斷開連接的具體過程,其中每一步是為什么那么做:

1)第一步:源主機A的應(yīng)用進程先向其TCP發(fā)出連接釋放請求,并且不再發(fā)送數(shù)據(jù)。TCP通知對方要釋放從A到B這個方向的連接,將發(fā)往主機B的TCP報文段首部的終止比特FIN置1,其序號X等于前面已傳送過的數(shù)據(jù)的最后一個字節(jié)的序號加1。

2)第二步:目標(biāo)主機B的TCP收到釋放連接通知后即發(fā)出確認(rèn),其序號為Y,確認(rèn)號為X+1,同時通知高層應(yīng)用進程,這樣,從A到B的連接就釋放了,連接處于半關(guān)閉狀態(tài),相當(dāng)于主機A向主機B說:“我已經(jīng)沒有數(shù)據(jù)要發(fā)送了。但如果還發(fā)送數(shù)據(jù),我仍接收?!贝撕螅鳈CB不再接收主機A發(fā)來的數(shù)據(jù)。但若主機B還有一些數(shù)據(jù)要發(fā)送主機A,則可以繼續(xù)發(fā)送。主機A只要正確收到數(shù)據(jù),仍應(yīng)向主機B發(fā)送確認(rèn)。

3)第三步:若主機B不再向主機A發(fā)送數(shù)據(jù),其應(yīng)用進程就通知TCP釋放連接。主機B發(fā)出的連接釋放報文段必須將終止比特FIN和確認(rèn)比特ACK置1,并使其序號仍為Y,但還必須重復(fù)上次已發(fā)送過的ACK=X+1。

4)?第四步:主機A必須對此發(fā)出確認(rèn),將ACK置1,ACK=Y(jié)+1,而自己的序號是X+1。這樣才把從B到A的反方向的連接釋放掉。主機A的TCP再向其應(yīng)用進程報告,整個連接已經(jīng)全部釋放。

10、tcp建立連接和斷開連接的各種過程中的狀態(tài)轉(zhuǎn)換細(xì)節(jié):

客戶端:主動打開SYN_SENT--->ESTABLISHED--->主動關(guān)閉FIN_WAIT_1--->FIN_WAIT_2--->TIME_WAIT

服務(wù)器端:LISTEN(被動打開)--->SYN_RCVD--->ESTABLISHED--->CLOSE_WAIT(被動關(guān)閉)--->LAST_ACK--->CLOSED

11、epool與select的區(qū)別:

問題的引出,當(dāng)需要讀兩個以上的I/O的時候,如果使用阻塞式的I/O,那么可能長時間的阻塞在一個描述符上面,另外的描述符雖然有數(shù)據(jù)但是不能讀出來,這樣實時性不能滿足要求,大概的解決方案有以下幾種:

1.使用多進程或者多線程,但是這種方法會造成程序的復(fù)雜,而且對與進程與線程的創(chuàng)建維護也需要很多的開銷。(Apache服務(wù)器是用的子進程的方式,優(yōu)點可以隔離用戶)

2.用一個進程,但是使用非阻塞的I/O讀取數(shù)據(jù),當(dāng)一個I/O不可讀的時候立刻返回,檢查下一個是否可讀,這種形式的循環(huán)為輪詢(polling),這種方法比較浪費CPU時間,因為大多數(shù)時間是不可讀,但是仍花費時間不斷反復(fù)執(zhí)行read系統(tǒng)調(diào)用。

3.異步I/O(asynchronous I/O),當(dāng)一個描述符準(zhǔn)備好的時候用一個信號告訴進程,但是由于信號個數(shù)有限,多個描述符時不適用。

4.一種較好的方式為I/O多路轉(zhuǎn)接(I/O multiplexing)(貌似也翻譯多路復(fù)用),先構(gòu)造一張有關(guān)描述符的列表(epoll中為隊列),然后調(diào)用一個函數(shù),直到這些描述符中的一個準(zhǔn)備好時才返回,返回時告訴進程哪些I/O就緒。select和epoll這兩個機制都是多路I/O機制的解決方案,select為POSIX標(biāo)準(zhǔn)中的,而epoll為Linux所特有的。

區(qū)別(epoll相對select優(yōu)點)主要有三:

1.select的句柄數(shù)目受限,在linux/posix_types.h頭文件有這樣的聲明:#define __FD_SETSIZE??? 1024? 表示select最多同時監(jiān)聽1024個fd。而epoll沒有,它的限制是最大的打開文件句柄數(shù)目。

2.epoll的最大好處是不會隨著FD的數(shù)目增長而降低效率,在selec中采用輪詢處理,其中的數(shù)據(jù)結(jié)構(gòu)類似一個數(shù)組的數(shù)據(jù)結(jié)構(gòu),而epoll是維護一個隊列,直接看隊列是不是空就可以了。epoll只會對"活躍"的socket進行操作---這是因為在內(nèi)核實現(xiàn)中epoll是根據(jù)每個fd上面的callback函數(shù)實現(xiàn)的。那么,只有"活躍"的socket才會主動的去調(diào)用 callback函數(shù)(把這個句柄加入隊列),其他idle狀態(tài)句柄則不會,在這點上,epoll實現(xiàn)了一個"偽"AIO。但是如果絕大部分的I/O都是“活躍的”,每個I/O端口使用率很高的話,epoll效率不一定比select高(可能是要維護隊列復(fù)雜)。

3.使用mmap加速內(nèi)核與用戶空間的消息傳遞。無論是select,poll還是epoll都需要內(nèi)核把FD消息通知給用戶空間,如何避免不必要的內(nèi)存拷貝就很重要,在這點上,epoll是通過內(nèi)核于用戶空間mmap同一塊內(nèi)存實現(xiàn)的。

12、epool中et和lt的區(qū)別與實現(xiàn)原理:

epoll有2種工作方式:LT和ET。

LT(level triggered)是缺省的工作方式,并且同時支持block和no-block socket.在這種做法中,內(nèi)核告訴你一個文件描述符是否就緒了,然后你可以對這個就緒的fd進行IO操作。如果你不作任何操作,內(nèi)核還是會繼續(xù)通知你 的,所以,這種模式編程出錯誤可能性要小一點。傳統(tǒng)的select/poll都是這種模型的代表.

ET (edge-triggered)是高速工作方式,只支持no-block socket。在這種模式下,當(dāng)描述符從未就緒變?yōu)榫途w時,內(nèi)核通過epoll告訴你。然后它會假設(shè)你知道文件描述符已經(jīng)就緒,并且不會再為那個文件描述 符發(fā)送更多的就緒通知,直到你做了某些操作導(dǎo)致那個文件描述符不再為就緒狀態(tài)了(比如,你在發(fā)送,接收或者接收請求,或者發(fā)送接收的數(shù)據(jù)少于一定量時導(dǎo)致 了一個EWOULDBLOCK 錯誤)。但是請注意,如果一直不對這個fd作IO操作(從而導(dǎo)致它再次變成未就緒),內(nèi)核不會發(fā)送更多的通知(only once),不過在TCP協(xié)議中,ET模式的加速效用仍需要更多的benchmark確認(rèn)。

epoll只有epoll_create,epoll_ctl,epoll_wait 3個系統(tǒng)調(diào)用。

13、寫一個server程序需要注意哪些問題:

14、ThreadLocal與其它同步機制的比較:

Threadlocal和其他所有的同步機制都是為了解決多線程中的對同一變量的訪問沖突,在普通的同步機制中,是通過對對象加鎖來實現(xiàn)多個線程對同一變量的安全訪問的。這時該變量是多個線程共享的,使用這種同步機制需要很細(xì)致的分析在什么時候?qū)ψ兞窟M行讀寫,什么時候需要鎖定某個對象,什么時候釋放該對象的索等等。所有這些都是因為多個線程共享了該資源造成的。Threadlocal就從另一個角度來解決多線程的并發(fā)訪問,Threadlocal會為每一個線程維護一個和該線程綁定的變量副本,從而隔離了多個線程的數(shù)據(jù)共享,每一個線程都擁有自己的變量副本,從而也就沒有必要對該變量進行同步了。ThreadLocal提供了線程安全的共享對象,在編寫多線程代碼時,可以把不安全的變量封裝進ThreadLocal。

總結(jié):當(dāng)然ThreadLocal并不能替代同步機制,兩者面向的問題領(lǐng)域不同。同步機制是為了同步多個線程對相同資源的并發(fā)訪問,是為了多個線程之間進行通信的有效方式;而ThreadLocal是隔離多個線程的數(shù)據(jù)共享,從根本上就不在多個線程之間共享資源(變量),這樣當(dāng)然不需要對多個線程進行同步了。所以,如果你需要進行多個線程之間進行通信,則使用同步機制;如果需要隔離多個線程之間的共享沖突,可以使用ThreadLocal,這將極大地簡化你的程序,使程序更加易讀、簡潔。

15、內(nèi)存池、進程池、線程池:

自定義內(nèi)存池的思想通過這個"池"字表露無疑,應(yīng)用程序可以通過系統(tǒng)的內(nèi)存分配調(diào)用預(yù)先一次性申請適當(dāng)大小的內(nèi)存作為一個內(nèi)存池,之后應(yīng)用程序自己對內(nèi)存的分配和釋放則可以通過這個內(nèi)存池來完成。只有當(dāng)內(nèi)存池大小需要動態(tài)擴展時,才需要再調(diào)用系統(tǒng)的內(nèi)存分配函數(shù),其他時間對內(nèi)存的一切操作都在應(yīng)用程序的掌控之中。 應(yīng)用程序自定義的內(nèi)存池根據(jù)不同的適用場景又有不同的類型。 從線程安全的角度來分,內(nèi)存池可以分為單線程內(nèi)存池多線程內(nèi)存池。單線程內(nèi)存池整個生命周期只被一個線程使用,因而不需要考慮互斥訪問的問題;多線程內(nèi)存池有可能被多個線程共享,因此則需要在每次分配和釋放內(nèi)存時加鎖。相對而言,單線程內(nèi)存池性能更高,而多線程內(nèi)存池適用范圍更廣。

從內(nèi)存池可分配內(nèi)存單元大小來分,可以分為固定內(nèi)存池和可變內(nèi)存池。所謂固定內(nèi)存池是指應(yīng)用程序每次從內(nèi)存池中分配出來的內(nèi)存單元大小事先已經(jīng)確定,是固定不變的;而可變內(nèi)存池則每次分配的內(nèi)存單元大小可以按需變化,應(yīng)用范圍更廣,而性能比固定內(nèi)存池要低。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容