1、TCP和UDP的區別:
1)TCP提供面向連接的傳輸,通信前要先建立連接(三次握手機制);UDP提供無連接的傳輸,通信前不需要建立連接。
2)TCP提供可靠的傳輸(有序,無差錯,不丟失,不重復);UDP提供不可靠的傳輸。
3)TCP面向字節流的傳輸,因此它能將信息分割成組,並在接收端將其重組;UDP是面向數據報的傳輸,沒有分組開銷。
4)TCP提供擁塞控制和流量控制機制;UDP不提供擁塞控制和流量控制機制。
2、流量控制和擁塞控制的實現機制:
1)TCP采用大小可變的滑動窗口機制實現流量控制功能。窗口的大小是字節。在TCP報文段首部的窗口字段寫入的數值就是當前給對方設置發送窗口的數據的上限。
在數據傳輸過程中,TCP提供了一種基於滑動窗口協議的流量控制機制,用接收端接收能力(緩沖區的容量)的大小來控制發送端發送的數據量。
2)采用滑動窗口機制還可對網絡進行擁塞控制,將網絡中的分組(TCP報文段作為其數據部分)數量維持在一定的數量之下,當超過該數值時,網絡的性能會急劇惡化。傳輸層的擁塞控制有慢開始(Slow-Start)、擁塞避免(Congestion Avoidance)、快重傳(Fast Retransmit)和快恢復(Fast Recovery)四種算法。
擁塞: 大量數據報涌入同一交換節點(如路由器),導致該節點資源耗盡而必須丟棄后面到達的數據報時,就是擁塞。
3、重傳機制:
TCP每發送一個報文段,就設置一次定時器。只要定時器設置的重發時間到而還沒有收到確認,就要重發這一報文段。
TCP環境
報文往返時間不定、有很大差別
A、B在一個局域網絡,往返時延很小
A、C在一個互聯網內,往返時延很大
因此,A很難確定一個固定的、與B、C通信都適用的定時器時間
TCP采用了一種自適應算法。這種算法記錄每一個報文段發出的時間,以及收到相應的確認報文段的時間。這兩個時間之差就是報文段的往返時延。將各個報文段的往返時延樣本加權平均,就得出報文段的平均往返時延T。
4、滑動窗口機制:
TCP 采用大小可變的滑動窗口進行流量控制。窗口大小的單位是字節。
在 TCP 報文段首部的窗口字段寫入的數值就是當前給對方設置的發送窗口數值的上限。發送窗口在連接建立時由雙方商定。但在通信的過程中,接收端可根據自己的資源情況,隨時動態地調整對方的發送窗口上限值(可增大或減小)。
5、多線程如何同步:
臨界區、互斥區、事件、信號量四種方式
臨界區(Critical Section)、互斥量(Mutex)、信號量(Semaphore)、事件(Event)的區別
1)、臨界區:通過對多線程的串行化來訪問公共資源或一段代碼,速度快,適合控制數據訪問。在任意時刻只允許一個線程對共享資源進行訪問,如果有多個線程試圖訪問公共資源,那么在有一個線程進入后,其他試圖訪問公共資源的線程將被掛起,並一直等到進入臨界區的線程離開,臨界區在被釋放后,其他線程才可以搶占。
2)、互斥量:采用互斥對象機制。 只有擁有互斥對象的線程才有訪問公共資源的權限,因為互斥對象只有一個,所以能保證公共資源不會同時被多個線程訪問。互斥不僅能實現同一應用程序的公共資源安全共享,還能實現不同應用程序的公共資源安全共享 .互斥量比臨界區復雜。因為使用互斥不僅僅能夠在同一應用程序不同線程中實現資源的安全共享,而且可以在不同應用程序的線程之間實現對資源的安全共享。
3)、信號量:它允許多個線程在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大線程數目 .信號量對象對線程的同步方式與前面幾種方法不同,信號允許多個線程同時使用共享資源,這與操作系統中的PV操作相同。它指出了同時訪問共享資源的線程最大數目。它允許多個線程在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大線程數目。
PV操作及信號量的概念都是由荷蘭科學家E.W.Dijkstra提出的。信號量S是一個整數,S大於等於零時代表可供並發進程使用的資源實體數,但S小於零時則表示正在等待使用共享資源的進程數。
P操作申請資源:
(1)S減1;
(2)若S減1后仍大於等於零,則進程繼續執行;
(3)若S減1后小於零,則該進程被阻塞后進入與該信號相對應的隊列中,然后轉入進程調度。
V操作 釋放資源:
(1)S加1;
(2)若相加結果大於零,則進程繼續執行;
(3)若相加結果小於等於零,則從該信號的等待隊列中喚醒一個等待進程,然后再返回原進程繼續執行或轉入進程調度。
4)、事 件: 通過通知操作的方式來保持線程的同步,還可以方便實現對多個線程的優先級比較的操作 .
總結:
1) 互斥量與臨界區的作用非常相似,但互斥量是可以命名的,也就是說它可以跨越進程使用。所以創建互斥量需要的資源更多,所以如果只為了在進程內部是用的話使用臨界區會帶來速度上的優勢並能夠減少資源占用量。因為互斥量是跨進程的互斥量一旦被創建,就可以通過名字打開它。
2) 互斥量(Mutex),信號燈(Semaphore),事件(Event)都可以被跨越進程使用來進行同步數據操作,而其他的對象與數據同步操作無關,但對於進程和線程來講,如果進程和線程在運行狀態則為無信號狀態,在退出后為有信號狀態。所以可以使用WaitForSingleObject來等待進程和線程退出。
3) 通過互斥量可以指定資源被獨占的方式使用,但如果有下面一種情況通過互斥量就無法處理,比如現在一位用戶購買了一份三個並發訪問許可的數據庫系統,可以根據用戶購買的訪問許可數量來決定有多少個線程/進程能同時進行數據庫操作,這時候如果利用互斥量就沒有辦法完成這個要求,信號燈對象可以說是一種資源計數器。
6、進程和線程的區別:
答:線程是指進程內的一個執行單元,也是進程內的可調度實體。與進程的區別:
(1)調度:線程作為調度和分配的基本單位,進程作為擁有資源的基本單位。
(2)並發性:不僅進程之間可以並發執行,同一個進程的多個線程之間也可並發執行。
(3)擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統資源,但可以訪問隸屬於進程的資源.
(4)系統開銷:在創建或撤消進程時,由於系統都要為之分配和回收資源,導致系統的開銷明顯大於創建或撤消線程時的開銷。
7、進程間通訊的方式有哪些,各有什么優缺點:
1)管道:管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關系的進程之間使用。進程的親緣關系通常是指父子進程關系。
2)有名管道(FIFO):有名管道也是半雙工的通信方式,但是允許在沒有親緣關系的進程之間使用,管道是先進先出的通信方式。
3)信號量:信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。
4)消息隊列:消息隊列是有消息的鏈表,存放在內核中並由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩沖區大小受限等缺點。
5)信號 ( sinal ) :信號是一種比較復雜的通信方式,用於通知接收進程某個事件已經發生。
6)共享內存( shared memory ) :共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的 IPC 方式,它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號量,配合使用,來實現進程間的同步和通信。
7)套接字( socket ) :套接字也是一種進程間通信機制,與其他通信機制不同的是,它可用於不同機器間的進程通信。
8、tcp連接建立的時候3次握手的具體過程,以及每一步原因:
(1) 第一步:源主機A的TCP向主機B發出連接請求報文段,其首部中的SYN(同步)標志位應置為1,表示想與目標主機B進行通信,並發送一個同步序列號X(例:SEQ=100)進行同步,表明在后面傳送數據時的第一個數據字節的序號是X+1(即101)。SYN同步報文會指明客戶端使用的端口以及TCP連接的初始序號。
(2) 第二步:目標主機B的TCP收到連接請求報文段后,如同意,則發回確認。在確認報中應將ACK位和SYN位置1,表示客戶端的請求被接受。確認號應為X+1(圖中為101),同時也為自己選擇一個序號Y。
(3) 第三步:源主機A的TCP收到目標主機B的確認后要向目標主機B給出確認,其ACK置1,確認號為Y+1,而自己的序號為X+1。TCP的標准規定,SYN置1的報文段要消耗掉一個序號。
運行客戶進程的源主機A的TCP通知上層應用進程,連接已經建立。當源主機A向目標主機B發送第一個數據報文段時,其序號仍為X+1,因為前一個確認報文段並不消耗序號。
當運行服務進程的目標主機B的TCP收到源主機A的確認后,也通知其上層應用進程,連接已經建立。至此建立了一個全雙工的連接。
9、tcp斷開連接的具體過程,其中每一步是為什么那么做:
1)第一步:源主機A的應用進程先向其TCP發出連接釋放請求,並且不再發送數據。TCP通知對方要釋放從A到B這個方向的連接,將發往主機B的TCP報文段首部的終止比特FIN置1,其序號X等於前面已傳送過的數據的最后一個字節的序號加1。
2)第二步:目標主機B的TCP收到釋放連接通知后即發出確認,其序號為Y,確認號為X+1,同時通知高層應用進程,這樣,從A到B的連接就釋放了,連接處於半關閉狀態,相當於主機A向主機B說:“我已經沒有數據要發送了。但如果還發送數據,我仍接收。”此后,主機B不再接收主機A發來的數據。但若主機B還有一些數據要發送主機A,則可以繼續發送。主機A只要正確收到數據,仍應向主機B發送確認。
3)第三步:若主機B不再向主機A發送數據,其應用進程就通知TCP釋放連接。主機B發出的連接釋放報文段必須將終止比特FIN和確認比特ACK置1,並使其序號仍為Y,但還必須重復上次已發送過的ACK=X+1。
4) 第四步:主機A必須對此發出確認,將ACK置1,ACK=Y+1,而自己的序號是X+1。這樣才把從B到A的反方向的連接釋放掉。主機A的TCP再向其應用進程報告,整個連接已經全部釋放。
10、tcp建立連接和斷開連接的各種過程中的狀態轉換細節:
客戶端:主動打開SYN_SENT--->ESTABLISHED--->主動關閉FIN_WAIT_1--->FIN_WAIT_2--->TIME_WAIT
服務器端:LISTEN(被動打開)--->SYN_RCVD--->ESTABLISHED--->CLOSE_WAIT(被動關閉)--->LAST_ACK--->CLOSED
11、epool與select的區別:
問題的引出,當需要讀兩個以上的I/O的時候,如果使用阻塞式的I/O,那么可能長時間的阻塞在一個描述符上面,另外的描述符雖然有數據但是不能讀出來,這樣實時性不能滿足要求,大概的解決方案有以下幾種:
1.使用多進程或者多線程,但是這種方法會造成程序的復雜,而且對與進程與線程的創建維護也需要很多的開銷。(Apache服務器是用的子進程的方式,優點可以隔離用戶)
2.用一個進程,但是使用非阻塞的I/O讀取數據,當一個I/O不可讀的時候立刻返回,檢查下一個是否可讀,這種形式的循環為輪詢(polling),這種方法比較浪費CPU時間,因為大多數時間是不可讀,但是仍花費時間不斷反復執行read系統調用。
3.異步I/O(asynchronous I/O),當一個描述符准備好的時候用一個信號告訴進程,但是由於信號個數有限,多個描述符時不適用。
4.一種較好的方式為I/O多路轉接(I/O multiplexing)(貌似也翻譯多路復用),先構造一張有關描述符的列表(epoll中為隊列),然后調用一個函數,直到這些描述符中的一個准備好時才返回,返回時告訴進程哪些I/O就緒。select和epoll這兩個機制都是多路I/O機制的解決方案,select為POSIX標准中的,而epoll為Linux所特有的。
區別(epoll相對select優點)主要有三:
1.select的句柄數目受限,在linux/posix_types.h頭文件有這樣的聲明:#define __FD_SETSIZE 1024 表示select最多同時監聽1024個fd。而epoll沒有,它的限制是最大的打開文件句柄數目。
2.epoll的最大好處是不會隨着FD的數目增長而降低效率,在selec中采用輪詢處理,其中的數據結構類似一個數組的數據結構,而epoll是維護一個隊列,直接看隊列是不是空就可以了。epoll只會對"活躍"的socket進行操作---這是因為在內核實現中epoll是根據每個fd上面的callback函數實現的。那么,只有"活躍"的socket才會主動的去調用 callback函數(把這個句柄加入隊列),其他idle狀態句柄則不會,在這點上,epoll實現了一個"偽"AIO。但是如果絕大部分的I/O都是“活躍的”,每個I/O端口使用率很高的話,epoll效率不一定比select高(可能是要維護隊列復雜)。
3.使用mmap加速內核與用戶空間的消息傳遞。無論是select,poll還是epoll都需要內核把FD消息通知給用戶空間,如何避免不必要的內存拷貝就很重要,在這點上,epoll是通過內核於用戶空間mmap同一塊內存實現的。
12、epool中et和lt的區別與實現原理:
epoll有2種工作方式:LT和ET。
LT(level triggered)是缺省的工作方式,並且同時支持block和no-block socket.在這種做法中,內核告訴你一個文件描述符是否就緒了,然后你可以對這個就緒的fd進行IO操作。如果你不作任何操作,內核還是會繼續通知你 的,所以,這種模式編程出錯誤可能性要小一點。傳統的select/poll都是這種模型的代表.
ET (edge-triggered)是高速工作方式,只支持no-block socket。在這種模式下,當描述符從未就緒變為就緒時,內核通過epoll告訴你。然后它會假設你知道文件描述符已經就緒,並且不會再為那個文件描述 符發送更多的就緒通知,直到你做了某些操作導致那個文件描述符不再為就緒狀態了(比如,你在發送,接收或者接收請求,或者發送接收的數據少於一定量時導致 了一個EWOULDBLOCK 錯誤)。但是請注意,如果一直不對這個fd作IO操作(從而導致它再次變成未就緒),內核不會發送更多的通知(only once),不過在TCP協議中,ET模式的加速效用仍需要更多的benchmark確認。
epoll只有epoll_create,epoll_ctl,epoll_wait 3個系統調用。
13、寫一個server程序需要注意哪些問題:
14、ThreadLocal與其它同步機制的比較:
Threadlocal和其他所有的同步機制都是為了解決多線程中的對同一變量的訪問沖突,在普通的同步機制中,是通過對對象加鎖來實現多個線程對同一變量的安全訪問的。這時該變量是多個線程共享的,使用這種同步機制需要很細致的分析在什么時候對變量進行讀寫,什么時候需要鎖定某個對象,什么時候釋放該對象的索等等。所有這些都是因為多個線程共享了該資源造成的。Threadlocal就從另一個角度來解決多線程的並發訪問,Threadlocal會為每一個線程維護一個和該線程綁定的變量副本,從而隔離了多個線程的數據共享,每一個線程都擁有自己的變量副本,從而也就沒有必要對該變量進行同步了。ThreadLocal提供了線程安全的共享對象,在編寫多線程代碼時,可以把不安全的變量封裝進ThreadLocal。
總結:當然ThreadLocal並不能替代同步機制,兩者面向的問題領域不同。同步機制是為了同步多個線程對相同資源的並發訪問,是為了多個線程之間進行通信的有效方式;而ThreadLocal是隔離多個線程的數據共享,從根本上就不在多個線程之間共享資源(變量),這樣當然不需要對多個線程進行同步了。所以,如果你需要進行多個線程之間進行通信,則使用同步機制;如果需要隔離多個線程之間的共享沖突,可以使用ThreadLocal,這將極大地簡化你的程序,使程序更加易讀、簡潔。
15、內存池、進程池、線程池:
自定義內存池的思想通過這個"池"字表露無疑,應用程序可以通過系統的內存分配調用預先一次性申請適當大小的內存作為一個內存池,之后應用程序自己對內存的分配和釋放則可以通過這個內存池來完成。只有當內存池大小需要動態擴展時,才需要再調用系統的內存分配函數,其他時間對內存的一切操作都在應用程序的掌控之中。 應用程序自定義的內存池根據不同的適用場景又有不同的類型。 從線程安全的角度來分,內存池可以分為單線程內存池和多線程內存池。單線程內存池整個生命周期只被一個線程使用,因而不需要考慮互斥訪問的問題;多線程內存池有可能被多個線程共享,因此則需要在每次分配和釋放內存時加鎖。相對而言,單線程內存池性能更高,而多線程內存池適用范圍更廣。
從內存池可分配內存單元大小來分,可以分為固定內存池和可變內存池。所謂固定內存池是指應用程序每次從內存池中分配出來的內存單元大小事先已經確定,是固定不變的;而可變內存池則每次分配的內存單元大小可以按需變化,應用范圍更廣,而性能比固定內存池要低。