1. 程式人生 > >【轉載】網絡編程面試題

【轉載】網絡編程面試題

更新 #define 兩臺 不存在 ipc 正常 表現 雙向 源地址

網絡編程面試題 1、tcp和udp的區別 TCP---傳輸控制協議,提供的是面向連接、可靠的字節流服務。當客戶和服務器彼此交換數據前,必須先在雙方之間建立一個TCP連接,之後才能傳輸數據。TCP提供超時重發,丟棄重復數據,檢驗數據,流量控制等功能,保證數據能從一端傳到另一端。 UDP---用戶數據報協議,是一個簡單的面向數據報的運輸層協議。UDP不提供可靠性,它只是把應用程序傳給IP層的數據報發送出去,但是並不能保證它們能到達目的地。由於UDP在傳輸數據報前不用在客戶和服務器之間建立一個連接,且沒有超時重發等機制,故而傳輸速度很快 2、流量控制和擁塞控制 擁塞控制 --- 網絡擁塞現象是指到達通信子網中某一部分的分組數量過多,使得該部分網絡來不及處理,以致引起這部分乃至整個網絡性能下降的現象,嚴重時甚至會導致網絡通信業務陷入停頓,即出現死鎖現象。擁塞控制是處理網絡擁塞現象的一種機制。 流量控制 --- 數據的傳送與接收過程當中很可能出現收方來不及接收的情況,這時就需要對發方進行控制,以免數據丟失。流量控制用於防止在端口阻塞的情況下丟幀,這種方法是當發送或接收緩沖區開始溢出時通過將阻塞信號發送回源地址實現的。流量控制可以有效的防止由於網絡中瞬間的大量數據對網絡帶來的沖擊,保證用戶網絡高效而穩定的運行。 3、多線程如何同步
windows --- 線程同步有四種方式:臨界區、內核對象、互斥量、信號量。 Linux --- 線程同步有最常用的是:互斥鎖、條件變量和信號量。 4、進程間通訊的方式有哪些,各有什麽優缺點 Linux 進程間通信(IPC)以下以幾部分發展而來:UNIX進程間通信、基於System V進程間通信、基於Socket進程間通信和POSIX進程間通信。 UNIX進程間通信方式包括:管道、FIFO、信號。 System V進程間通信方式包括:System V消息隊列、System V信號燈、System V共享內存 POSIX進程間通信包括:posix消息隊列、posix信號燈、posix共享內存。
現在linux使用的進程間通信方式:
(1)管道(pipe)和有名管道(FIFO)
(2)信號(signal)
(3)消息隊列
(4)共享內存
(5)信號量
(6)套接字(socket) 管道: 優點是所有的UNIX實現都支持, 並且在最後一個訪問管道的進程終止後,管道就被完全刪除; 缺陷是管道只允許單向傳輸或者用於父子進程之間 系統IPC: 優點是功能強大,能在毫不相關進程之間進行通訊; 缺陷是關鍵字KEY_T使用了內核標識,占用了內核資源,而且只能被顯式刪除,而且不能使用SOCKET的一些機制,例如select,epoll等. socket可以跨網絡通訊,其他進程間通訊的方式都不可以,只能是本機進程通訊。 5、tcp連接建立的時候3次握手,斷開連接的4次握手的具體過程
三次握手 --- 第一次握手是客戶端connect連接到server,server accept client的請求之後,向client端發送一個消息,相當於說我都準備好了,你連接上我了,這是第二次握手,第3次握手就是client向server發送的,就是對第二次握手消息的確認。之後client和server就開始通訊了。 四次握手 --- 斷開連接的一端發送close請求是第一次握手,另外一端接收到斷開連接的請求之後需要對close進行確認,發送一個消息,這是第二次握手,發送了確認消息之後還要向對端發送close消息,要關閉對對端的連接,這是第3次握手,而在最初發送斷開連接的一端接收到消息之後,進入到一個很重要的狀態time_wait狀態,這個狀態也是面試官經常問道的問題,最後一次握手是最初發送斷開連接的一端接收到消息之後。對消息的確認。 6、epoll與select的區別
1)select在一個進程中打開的最大fd是有限制的,由FD_SETSIZE設置,默認值是2048。不過 epoll則沒有這個限制,它所支持的fd上限是最大可以打開文件的數目,這個數字一般遠大於2048,一般來說內存越大,fd上限越大,1G內存都能達到大約10w左右。 2)select的輪詢機制是系統會去查找每個fd是否數據已準備好,當fd很多的時候,效率當然就直線下降了,epoll采用基於事件的通知方式,一旦某個fd數據就緒時,內核會采用類似callback的回調機制,迅速激活這個文件描述符,而不需要不斷的去輪詢查找就緒的描述符,這就是epoll高效最本質的原因。 3)無論是select還是epoll都需要內核把FD消息通知給用戶空間,如何避免不必要的內存拷貝就很重要,在這點上,epoll是通過內核於用戶空間mmap同一塊內存實現的,而select則做了不必要的拷貝 7、epoll中et和lt的區別與實現原理 LT:水平觸發,效率會低於ET觸發,尤其在大並發,大流量的情況下。但是LT對代碼編寫要求比較低,不容易出現問題。LT模式服務編寫上的表現是:只要有數據沒有被獲取,內核就不斷通知你,因此不用擔心事件丟失的情況。 ET:邊緣觸發,效率非常高,在並發,大流量的情況下,會比LT少很多epoll的系統調用,因此效率高。但是對編程要求高,需要細致的處理每個請求,否則容易發生丟失事件的情況。 8、connect方法會阻塞,請問有什麽方法可以避免其長時間阻塞? 最通常的方法最有效的是加定時器;也可以采用非阻塞模式。 或者考慮采用異步傳輸機制,同步傳輸與異步傳輸的主要區別在於同步傳輸中,如果調用recvfrom後會一致阻塞運行,從而導致調用線程暫停運行;異步傳輸機制則不然,會立即返回。 9、網絡中,如果客戶端突然掉線或者重啟,服務器端怎麽樣才能立刻知道? 答:若客戶端掉線或者重新啟動,服務器端會收到復位信號,每一種tcp/ip得實現不一樣,控制機制也不一樣。

10、在子網210.27.48.21/30種有多少個可用地址?分別是什麽? 簡: 30表示的是網絡號(network number)是30位,剩下2位中11是廣播(broadcast)地址,00是multicast地址,只有01和10可以作為host address。 詳: 210.27.48.21/30代表的子網的網絡號是30位,即網絡號是210.27.48.21 & 255.255.255.251=210.27.48.20,此子網的地址空間是2位,即可以有4個地址:210.27.48.20, 210.27.48.21, 210.27.48.22, 210.27.48.23。第一個地址的主機號(host number/id)是0,而主機號0代表的是multicast地址。最後一個地址的最後兩位是11,主機號每一位都為1代表的是廣播(broadcast)地址。所以只有中間兩個地址可以給host使用。其實那個問題本身不準確,廣播或multicast地止也是可以使用的地址,所以回答4也應該正確,當然問的人也可能是想要你回答2。我個人覺得最好的回答是一個廣播地址,一個multicast地址,2個unicast地址。
11、TTL是什麽?有什麽用處,通常那些工具會用到它?(ping? traceroute? ifconfig? netstat?) 簡: TTL是Time To Live,一般是hup count,每經過一個路由就會被減去一,如果它變成0,包會被丟掉。它的主要目的是防止包在有回路的網絡上死轉,浪費網絡資源。ping和traceroute用到它。 詳: TTL是Time To Live,目前是hup count,當包每經過一個路由器它就會被減去一,如果它變成0,路由器就會把包丟掉。IP網絡往往帶有環(loop),比如子網A和子網B有兩個路由器相連,它就是一個loop。TTL的主要目的是防止包在有回路的網絡上死轉,因為包的TTL最終後變成0而使得此包從網上消失(此時往往路由器會送一個ICMP包回來,traceroute就是根據這個做的)。ping會送包出去,所以裏面有它,但是ping不一定非要不可它。traceroute則是完全因為有它才能成的。ifconfig是用來配置網卡的,netstat -rn 是用來列路由表的,所以都用不著它

12、路由表示做什麽用的?在linux環境中怎麽來配置一條默認路由? 簡: 路由表是用來決定如何將包從一個子網傳送到另一個子網的,換局話說就是用來決定從一個網卡接收到的包應該送的哪一張網卡上的。在Linux上可以用“route add default gw <默認路由器IP>”來配置一條默認路由。 詳: 路由表是用來決定如何將包從一個子網傳送到另一個子網的,換局話說就是用來決定從一個網卡接收到的包應該送的哪一張網卡上的。路由表的每一行至少有目標網絡號、netmask、到這個子網應該使用的網卡。當路由器從一個網卡接收到一個包時,它掃描路由表的每一行,用裏面的netmask和包裏的目標IP地址做並邏輯運算(&)找出目標網絡號,如果此網絡號和這一行裏的網絡號相同就將這條路由保留下來做為備用路由,如果已經有備用路由了就在這兩條路由裏將網絡號最長的留下來,另一條丟掉,如此接著掃描下一行直到結束。如果掃描結束任沒有找到任何路由,就用默認路由。確定路由後,直接將包送到對應的網卡上去。在具體的實現中,路由表可能包含更多的信息為選路由算法的細節所用。題外話:路由算法其實效率很差,而且不scalable,解決辦法是使用IP交換機,比如MPLS。
在Linux上可以用“route add default gw <默認路由器IP>”來配置一條默認路由。

13、在網絡中有兩臺主機A和B,並通過路由器和其他交換設備連接起來,已經確認物理連接正確無誤,怎麽來測試這兩臺機器是否連通?如果不通,怎麽來判斷故障點?怎麽排除故障? 答:測試這兩臺機器是否連通:從一臺機器ping另一臺機器,如果ping不通,用traceroute可以確定是哪個路由器不能連通,然後再找問題是在交換設備/hup/cable等。
14、網絡編程中設計並發服務器,使用多進程 與 多線程 ,請問有什麽區別? 答案一: 1)進程:子進程是父進程的復制品。子進程獲得父進程數據空間、堆和棧的復制品。 2)線程:相對與進程而言,線程是一個更加接近與執行體的概念,它可以與同進程的其他線程共享數據,但擁有自己的棧空間,擁有獨立的執行序列。 兩者都可以提高程序的並發度,提高程序運行效率和響應時間。
線程和進程在使用上各有優缺點:線程執行開銷小,但不利於資源管理和保護;而進程正相反。同時,線程適合於在SMP機器上運行,而進程則可以跨機器遷移。

答案二:
根本區別就一點:用多進程每個進程有自己的地址空間(address space),線程則共享地址空間。所有其它區別都是由此而來的: 1)速度:線程產生的速度快,線程間的通訊快、切換快等,因為他們在同一個地址空間內。 2)資源利用率:線程的資源利用率比較好也是因為他們在同一個地址空間內。 3)同步問題:線程使用公共變量/內存時需要使用同步機制還是因為他們在同一個地址空間內。 15、 網絡編程的一般步驟 對於TCP連接: 1.服務器端1)創建套接字create;2)綁定端口號bind;3)監聽連接listen;4)接受連接請求accept,並返回新的套接字;5)用新返回的套接字recv/send;6)關閉套接字。 2.客戶端1)創建套接字create; 2)發起建立連接請求connect; 3)發送/接收數據send/recv;4)關閉套接字。 TCP總結: Server端:create -- bind -- listen-- accept-- recv/send-- close Client端:create------- conncet------send/recv------close. 對於UDP連接: 1.服務器端:1)創建套接字create;2)綁定端口號bind;3)接收/發送消息recvfrom/sendto;4)關閉套接字。 2.客戶端:1)創建套接字create;2)發送/接收消息sendto/recvfrom;3)關閉套接字. UDP總結: Server端:create----bind ----recvfrom/sendto----close Client端:create---- sendto/recvfrom----close. 16、TCP的重發機制是怎麽實現的? 1)滑動窗口機制,確立收發的邊界,能讓發送方知道已經發送了多少(已確認)、尚未確認的字節數、尚待發送的字節數;讓接收方知道(已經確認收到的字節數)。 2)選擇重傳,用於對傳輸出錯的序列進行重傳。 17、TCP為什麽不是兩次連接?而是三次握手? 如果A與B兩個進程通信,如果僅是兩次連接。可能出現的一種情況就是:A發送完請報文以後,由於網絡情況不好,出現了網絡擁塞,即B延時很長時間後收到報文,即此時A將此報文認定為失效的報文。B收到報文後,會向A發起連接。此時兩次握手完畢,B會認為已經建立了連接可以通信,B會一直等到A發送的連接請求,而A對失效的報文回復自然不會處理。依次會陷入B忙等的僵局,造成資源的浪費。 18、C++模板的作用。 將算法與具體對象分離,與類型無關,通用,節省精力 19、socket編程,如果client斷電了,服務器如何快速知道??? 使用定時器(適合有數據流動的情況); 使用socket選項SO_KEEPALIVE(適合沒有數據流動的情況); 20、fork()一子進程程後 父進程癿全局變量能不能使用??? fork後子進程將會擁有父進程的幾乎一切資源,父子進程的都各自有自己的全局變量。不能通用,不同於線程。對於線程,各個線程共享全局變量。 21、4G的long型整數中找到一個最大的,如何做???? 要找到最大的肯定要遍歷所有的數的,而且不能將數據全部讀入內存,可能不足。算法的時間復雜度肯定是O(n) 感覺就是遍歷,比較。。。。還能怎麽改進呢???? 可以改進的地方,就是讀入內存的時候,一次多讀些。。。。 需要註意的就是每次從磁盤上盡量多讀一些數到內存區,然後處理完之後再讀入一批。減少IO次數,自然能夠提高效率。而對於類快速排序方法,稍微要麻煩一些: 分批讀入,假設是M個數,然後從這M個數中選出n個最大的數緩存起來,直到所有的N個數都分批處理完之後,再將各批次緩存的n個數合並起來再進行一次類快 速排序得到最終的n個最大的數就可以了。在運行過程中,如果緩存數太多,可以不斷地將多個緩存合並,保留這些緩存中最大的n個數即可。由於類快速排序的時 間復雜度是O(N),這樣分批處理再合並的辦法,依然有極大的可能會比堆和敗者樹更優。當然,在空間上會占用較多的內存。 此題還有個變種,就是尋找K個最大或者最小的數。有以下幾種算法: 容量為K的最大堆/最小堆,假設K可以裝入內存; 如果N個數可以裝入內存,且都小於MAX,那麽可以開辟一個MAX大的數組,類似計數排序。。。從數組尾部掃描K個最大的數,頭部掃描K個最小的數。 22、有千萬個string在內存怎麽高速查找,插入和刪除??? 對千萬個string做hash,可以實現高速查找,找到了,插入和刪除就很方便了。 23、tcp三次握手的過程,accept發生在三次握手哪個階段? client 的 connect 引起3次握手 server 在socket, bind, listen後,阻塞在accept,三次握手完成後,accept返回一個fd,因此accept發生在三次握手之後。。。。。。 24、Tcp流, udp的數據報,之間有什麽區別,為什麽TCP要叫做數據流? TCP本身是面向連接的協議,S和C之間要使用TCP,必須先建立連接,數據就在該連接上流動,可以是雙向的,沒有邊界。所以叫數據流 ,占系統資源多 UDP不是面向連接的,不存在建立連接,釋放連接,每個數據包都是獨立的包,有邊界,一般不會合並。 TCP保證數據正確性,UDP可能丟包,TCP保證數據順序,UDP不保證 25、volatile的含義。 變量可能在編譯器的控制或監控之外改變,告訴編譯器不要優化該變量,如被系統時鐘更新的變量。 26、OFFSETOF(s, m)的宏定義,s是結構類型,m是s的成員,求m在s中的偏移量。 #define OFFSETOF(s, m) size_t(&((s*)0)->m) 27、socket在什麽情況下可讀? 1. 接收緩沖區有數據,一定可讀 2. 對方正常關閉socket,也是可讀 3. 對於偵聽socket,有新連接到達也可讀 4.socket有錯誤發生,且pending 28、流量控制與擁塞控制的區別,節點計算機怎樣感知網絡擁塞了??? 擁塞控制是把整體看成一個處理對象的,流量控制是對單個的節點。 感知的手段應該不少,比如在TCP協議裏,TCP報文的重傳本身就可以作為擁塞的依據。依據這樣的原理, 應該可以設計出很多手段。 29、C++虛函數是如何實現的??? 使用虛函數表。 C++對象使用虛表, 如果是基類的實例,對應位置存放的是基類的函數指針;如果是繼承類,對應位置存放的是繼承類的函數指針(如果在繼承類有實現)。所以 ,當使用基類指針調用對象方法時,也會根據具體的實例,調用到繼承類的方法。 30、C++的虛函數有什麽作用? ?? 虛函數作用是實現多態,更重要的,虛函數其實是實現封裝,使得使用者不需要關心實現的細節。在很多設計模式中都是這樣用法,例如Factory、Bridge、Strategy模式。 31、 TCP通訊中,select到讀事件,但是讀到的數據量是0,為什麽,如何解決???? select 返回0代表超時。select出錯返回-1。 select到讀事件,但是讀到的數據量為0,說明對方已經關閉了socket的讀端。本端關閉讀即可。 當select出錯時,會將接口置為可讀又可寫。這時就要通過判斷select的返回值為-1來區分。 32、給出float與“零值”比較的 if 語句(假設變量名為var)??? const float EPSINON = 0.00001; if ((x >= - EPSINON) && (x <= EPSINON)

【轉載】網絡編程面試題