1. 程式人生 > >C/C++ Linux系統程式設計筆試題目

C/C++ Linux系統程式設計筆試題目

http://www.360doc.com/content/14/0724/21/1073512_396828405.shtml

1:tcp和udp的區別

TCP:是面向連線的流傳輸控制協議,具有高可靠性,確保傳輸資料的正確性,有驗證重發機制,因此不會出現丟失或亂序。

UDP:是無連線的資料報服務,不對資料報進行檢查與修改,無須等待對方的應答,會出現分組丟失、重複、亂序,但具有較好的實時性,UDP段結構比TCP的段結構簡單,因此網路開銷也小。

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)

5:tcp連線建立的時候3次握手,斷開連線的4次握手的具體過程

建立連線採用的3次握手協議,具體是指:
第一次握手是客戶端connect連線到server,server accept client的請求之後,向client端傳送一個訊息,相當於說我都準備好了,你連線上我了,這是第二次握手,第3次握手就是client向server傳送的,就是對第二次握手訊息的確認。之後client和server就開始通訊了。
斷開連線的4次握手,具體如下:
斷開連線的一端傳送close請求是第一次握手,另外一端接收到斷開連線的請求之後需要對close進行確認,傳送一個訊息,這是第二次握手,傳送了確認訊息之後還要向對端傳送close訊息,要關閉對對端的連線,這是第3次握手,而在最初發送斷開連線的一端接收到訊息之後,進入到一個很重要的狀態time_wait狀態,這個狀態也是面試官經常問道的問題,最後一次握手是最初發送斷開連線的一端接收到訊息之後。對訊息的確認。


6:epoll與select的區別

select在一個程序中開啟的最大fd是有限制的,由FD_SETSIZE設定,預設值是2048。不過 epoll則沒有這個限制,它所支援的fd上限是最大可以開啟檔案的數目,這個數字一般遠大於2048,一般來說記憶體越大,fd上限越大,1G記憶體都能達到大約10w左右。

select的輪詢機制是系統會去查詢每個fd是否資料已準備好,當fd很多的時候,效率當然就直線下降了,epoll採用基於事件的通知方式,一旦某個fd資料就緒時,核心會採用類似callback的回撥機制,迅速啟用這個檔案描述符,而不需要不斷的去輪詢查詢就緒的描述符,這就是epoll高效最本質的原因。

無論是select還是epoll都需要核心把FD訊息通知給使用者空間,如何避免不必要的記憶體拷貝就很重要,在這點上,epoll是通過核心於使用者空間mmap同一塊記憶體實現的,而select則做了不必要的拷貝

7:epoll中et和lt的區別與實現原理

LT:水平觸發,效率會低於ET觸發,尤其在大併發,大流量的情況下。但是LT對程式碼編寫要求比較低,不容易出現問題。LT模式服務編寫上的表現是:只要有資料沒有被獲取,核心就不斷通知你,因此不用擔心事件丟失的情況。
ET:邊緣觸發,效率非常高,在併發,大流量的情況下,會比LT少很多epoll的系統呼叫,因此效率高。但是對程式設計要求高,需要細緻的處理每個請求,否則容易發生丟失事件的情況。

=======================================================================

1、connect方法會阻塞,請問有什麼方法可以避免其長時間阻塞?
答:最通常的方法最有效的是加定時器;也可以採用非阻塞模式。

2、網路中,如果客戶端突然掉線或者重啟,伺服器端怎麼樣才能立刻知道?
答:若客戶端掉線或者重新啟動,伺服器端會收到復位訊號,每一種tcp/ip得實現不一樣,控制機制也不一樣。

3.在子網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地址。

4.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 是用來列路由表的,所以都用不著它

5.路由表示做什麼用的?在linux環境中怎麼來配置一條預設路由?
答:
簡:路由表是用來決定如何將包從一個子網傳送到另一個子網的,換局話說就是用來決定從一個網絡卡接收到的包應該送的哪一張網絡卡上的。在Linux上可以用“route add default gw <預設路由器IP>”來配置一條預設路由。

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

6.在網路中有兩臺主機A和B,並通過路由器和其他交換裝置連線起來,已經確認物理連線正確無誤,怎麼來測試這兩臺機器是否連通?如果不通,怎麼來判斷故障點?怎麼排除故障?
答:測試這兩臺機器是否連通:從一臺機器ping另一臺機器
     如果ping不通,用traceroute可以確定是哪個路由器不能連通,然後再找問題是在交換裝置/hup/cable等。

7.網路程式設計中設計併發伺服器,使用多程序 與 多執行緒 ,請問有什麼區別? 
答案一:
1,程序:子程序是父程序的複製品。子程序獲得父程序資料空間、堆和棧的複製品。
2,執行緒:相對與程序而言,執行緒是一個更加接近與執行體的概念,它可以與同進程的其他執行緒共享資料,但擁有自己的棧空間,擁有獨立的執行序列。
兩者都可以提高程式的併發度,提高程式執行效率和響應時間。
執行緒和程序在使用上各有優缺點:執行緒執行開銷小,但不利於資源管理和保護;而程序正相反。同時,執行緒適合於在SMP機器上執行,而程序則可以跨機器遷移。

答案二:
根本區別就一點:用多程序每個程序有自己的地址空間(address space),執行緒則共享地址空間。所有其它區別都是由此而來的:
1。速度:執行緒產生的速度快,執行緒間的通訊快、切換快等,因為他們在同一個地址空間內。
2。資源利用率:執行緒的資源利用率比較好也是因為他們在同一個地址空間內。
3。同步問題:執行緒使用公共變數/記憶體時需要使用同步機制還是因為他們在同一個地址空間內。
等等

3. 網路程式設計的一般步驟

對於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.


5. TCP的重發機制是怎麼實現的?

       1.滑動視窗機制,確立收發的邊界,能讓傳送方知道已經發送了多少(已確認)、尚未確認的位元組數、尚待發送的位元組數;讓接收方知道(已經確認收到的位元組數)。

       2.選擇重傳,用於對傳輸出錯的序列進行重傳。

6. TCPUDP的區別?

       1)TCP面向連線(三次握手機制),通訊前需要先建立連線;UDP面向無連線,通訊前不需要建立連線;

       2)TCP保障可靠傳輸(按序、無差錯、不丟失、不重複);UDP不保障可靠傳輸,使用最大努力交付;

       3)TCP面向位元組流的傳輸,UDP面向資料報的傳輸。

   TCP—傳輸控制協議,提供的是面向連線、可靠的位元組流服務。當客戶和伺服器彼此交換資料前,必須先在雙方之間建立一個TCP連線,之後才能傳輸資料。TCP提供超時重發,丟棄重複資料,檢驗資料,流量控制等功能,保證資料能從一端傳到另一端。
UDP—使用者資料報協議,是一個簡單的面向資料報的運輸層協議。UDP不提供可靠性,它只是把應用程式傳給IP層的資料報傳送出去,但是並不能保證它們能到達目的地。由於UDP在傳輸資料報前不用在客戶和伺服器之間建立一個連線,且沒有超時重發等機制,故而傳輸速度很快


8.TCP為什麼不是兩次連線?而是三次握手?

如果AB兩個程序通訊,如果僅是兩次連線。可能出現的一種情況就是:A傳送完請報文以後,由於網路情況不好,出現了網路擁塞,即B延時很長時間後收到報文,即此時A將此報文認定為失效的報文。B收到報文後,會向A發起連線。此時兩次握手完畢,B會認為已經建立了連線可以通訊,B會一直等到A傳送的連線請求,而A對失效的報文回覆自然不會處理。依次會陷入B忙等的僵局,造成資源的浪費。

9. connect方法會阻塞,請問有什麼方法可以避免其長時間阻塞?

可以考慮採用非同步傳輸機制,同步傳輸與非同步傳輸的主要區別在於同步傳輸中,如果呼叫recvfrom後會一致阻塞執行,從而導致呼叫執行緒暫停執行;非同步傳輸機制則不然,會立即返回。


8.網路程式設計中設計併發伺服器,使用多程序多執行緒,請問有什麼區別?

答案一:

1,程序:子程序是父程序的複製品。子程序獲得父程序資料空間、堆和棧的複製品。

2,執行緒:相對與程序而言,執行緒是一個更加接近與執行體的概念,它可以與同進程的其他執行緒共享資料,但擁有自己的棧空間,擁有獨立的執行序列。兩者都可以提高程式的併發度,提高程式執行效率和響應時間。

執行緒和程序在使用上各有優缺點:執行緒執行開銷小,但不利於資源管理和保護;而程序正相反。同時,執行緒適合於在SMP機器上執行,而程序則可以跨機器遷移。

答案二:

根本區別就一點:用多程序每個程序有自己的地址空間(address space),執行緒則共享地址空間。所有其它區別都是由此而來的:

1。速度:執行緒產生的速度快,執行緒間的通訊快、切換快等,因為他們在同一個地址空間內。

2。資源利用率:執行緒的資源利用率比較好也是因為他們在同一個地址空間內。

3。同步問題:執行緒使用公共變數/記憶體時需要使用同步機制還是因為他們在同一個地址空間內。

等等


17.流量控制和擁塞控制的實現機制


擁塞控制
網路擁塞現象是指到達通訊子網中某一部分的分組數量過多,使得該部分網路來不及處理,以致引起這部分乃至整個網路效能下降的現象,嚴重時甚至會導致網路通訊業務陷入停頓,即出現死鎖現象。擁塞控制是處理網路擁塞現象的一種機制。
流量控制
資料的傳送與接收過程當中很可能出現收方來不及接收的情況,這時就需要對發方進行控制,以免資料丟失。

流量控制機制:

  流量控制用於防止在埠阻塞的情況下丟幀,這種方法是當傳送或接收緩衝區開始溢位時通過將阻塞訊號傳送回源地址實現的。流量控制可以有效的防止由於網路中瞬間的大量資料對網路帶來的衝擊,保證使用者網路高效而穩定的執行。
18.多執行緒如何同步:

 在這裡簡單說一下linux多執行緒同步的方法吧(win上有一定的差別,也有一定的累似)

1:執行緒資料,每個執行緒資料建立一個鍵,它和這個鍵相關聯,在各個執行緒裡,都使用這個鍵來指代執行緒資料,但在不同的執行緒裡,這個鍵代表的資料是不同的,在同一個執行緒裡,它代表同樣的資料內容。以此來達到執行緒安全的目的。
2:互斥鎖,就是在各個執行緒要使用的一些公共資料之前加鎖,使用之後釋放鎖,這個是非常常用的執行緒安全控制的方法,而頻繁的加解鎖也對效率有一定的影響。
3:條件變數,而條件變數通過允許執行緒阻塞和等待另一個執行緒傳送訊號的方法彌補了互斥鎖的不足,它常和互斥鎖一起使用。使用時,條件變數被用來阻塞一個執行緒,當條件不滿足時,執行緒往往解開相應的互斥鎖並等待條件發生變化。一旦其它的某個執行緒改變了條件變數,它將通知相應的條件變數喚醒一個或多個正被此條件變數阻塞的執行緒。這些執行緒將重新鎖定互斥鎖並重新測試條件是否滿足。一般說來,條件變數被用來進行執行緒間的同步。
4:訊號量,訊號量本質上是一個非負的整數計數器,它被用來控制對公共資源的訪問。當公共資源增加時,呼叫函式sem_post()增加訊號量。只有當訊號量值大於0時,才能使用公共資源,使用後,函式sem_wait()減少訊號量。函式sem_trywait()和函式pthread_ mutex_trylock()起同樣的作用,它是函式sem_wait()的非阻塞版本
另外pthread_join也可以等待一個執行緒的終止。

19.程序間通訊的方式有哪些,各有什麼優缺點

程序間通訊主要包括管道, 系統IPC(包括訊息佇列,訊號量,共享儲存), socket.

管道包括三種:1)普通管道PIPE, 通常有種限制,一是半雙工,只能單向傳輸;二是隻能在父子程序間使用. 2)流管道s_pipe: 去除了第一種限制,可以雙向傳輸. 3)命名管道:name_pipe, 去除了第二種限制,可以在許多並不相關的程序之間進行通訊.

系統IPC的三種方式類同,都是使用了核心裡的識別符號來識別

管道: 優點是所有的UNIX實現都支援, 並且在最後一個訪問管道的程序終止後,管道就被完全刪除;缺陷是管道只允許單向傳輸或者用於父子程序之間

系統IPC: 優點是功能強大,能在毫不相關程序之間進行通訊; 缺陷是關鍵字KEY_T使用了核心標識,佔用了核心資源,而且只能被顯式刪除,而且不能使用SOCKET的一些機制,例如select,epoll等.

socket可以跨網路通訊,其他程序間通訊的方式都不可以,只能是本機程序通訊。

20.tcp連線建立的時候3次握手的具體過程,以及其中的每一步是為什麼

建立連線採用的3次握手協議,具體是指:

第一次握手是客戶端connect連線到server,server accept client的請求之後,向client端傳送一個訊息,相當於說我都準備好了,你連線上我了,這是第二次握手,第3次握手就是client向server傳送的,就是對第二次握手訊息的確認。之後client和server就開始通訊了。

21.tcp斷開連線的具體過程,其中每一步是為什麼那麼做

斷開連線的4次握手,具體如下:

斷開連線的一端傳送close請求是第一次握手,另外一端接收到斷開連線的請求之後需要對close進行確認,傳送一個訊息,這是第二次握手,傳送了確認訊息之後還要向對端傳送close訊息,要關閉對對端的連線,這是第3次握手,而在最初發送斷開連線的一端接收到訊息之後,進入到一個很重要的狀態time_wait狀態,這個狀態也是面試官經常問道的問題,最後一次握手是最初發送斷開連線的一端接收到訊息之後。對訊息的確認。

=======================

1.C++模板的作用。  將演算法與具體物件分離,與型別無關,通用,節省精力 2.socket程式設計,如果client斷電了,伺服器如何快速知道??? 有以下幾個技術: 使用定時器(適合有資料流動的情況); 使用socket選項SO_KEEPALIVE(適合沒有資料流動的情況);  3.fork()一子程序程後 父程序癿全域性變數能不能使用??? fork後子程序將會擁有父程序的幾乎一切資源,父子程序的都各自有自己的全域性變數。不能通用,不同於執行緒。對於執行緒,各個執行緒共享全域性變數。 4.4G的long型整數中找到一個最大的,如何做???? 我的想法是要找到最大的肯定要遍歷所有的數的,而且不能將資料全部讀入記憶體,可能不足。演算法的時間複雜度肯定是O(n) 感覺就是遍歷,比較。。。。還能怎麼改進呢???? 可以改進的地方,就是讀入記憶體的時候,一次多讀些。。。。 需 要注意的就是每次從磁碟上儘量多讀一些數到記憶體區,然後處理完之後再讀入一批。減少IO次數,自然能夠提高效率。而對於類快速排序方法,稍微要麻煩一些: 分批讀入,假設是M個數,然後從這M個數中選出n個最大的數快取起來,直到所有的N個數都分批處理完之後,再將各批次快取的n個數合併起來再進行一次類快 速排序得到最終的n個最大的數就可以了。在執行過程中,如果快取數太多,可以不斷地將多個快取合併,保留這些快取中最大的n個數即可。由於類快速排序的時 間複雜度是O(N),這樣分批處理再合併的辦法,依然有極大的可能會比堆和敗者樹更優。當然,在空間上會佔用較多的記憶體。  此題還有個變種,就是尋找K個最大或者最小的數。有以下幾種演算法: 容量為K的最大堆/最小堆,假設K可以裝入記憶體; 如果N個數可以裝入記憶體,且都小於MAX,那麼可以開闢一個MAX大的陣列,類似計數排序。。。從陣列尾部掃描K個最大的數,頭部掃描K個最小的數。 5.有千萬個string在記憶體怎麼高速查詢,插入和刪除??? 對千萬個string做hash,可以實現高速查詢,找到了,插入和刪除就很方便了。 關鍵是如何做hash,對string做hash,要減少碰撞頻率。 In theStringclass, for example, the hash codehof a stringsof lengthnis calculated as
\( \texttt{h} \;=\; \texttt{s[0]}*31^{n-1} + \texttt{s[1]}*31^{n-2} + \cdots + \texttt{s[n-1]} \)
or, in code,
int h = 0; for (int i = 0; i < n; i++) {     h = 31*h + s.charAt(i); }
In general the arithmetic operations in such expressions will use 32-bit modular arithmeticignoring overflow
在實際中,BKDRhash函式比較好
// BKDR Hash unsigned int BKDRHash(char *str) { unsigned int seed = 131; // 31 131 1313 13131 131313 etc.. unsigned inthash = 0;   while (*str) { hash = hash * seed + (*str++); }   return (hash & 0x7FFFFFFF); }
6.tcp三次握手的過程,accept發生在三次握手哪個階段?
三次握手:C----->SYN K
              S------>ACK K+1 SYN J
              C------->ACK J+1   
              DONE!
client 的 connect  引起3次握手
server 在socket, bind, listen後,阻塞在accept,三次握手完成後,accept返回一個fd,
因此accept發生在三次握手之後。。。。。。
7.Tcp流, udp的資料報,之間有什麼區別,為什麼TCP要叫做資料流?
TCP本身是面向連線的協議,S和C之間要使用TCP,必須先建立連線,資料就在該連線上流動,可以是雙向的,沒有邊界。所以叫資料流 ,佔系統資源多
UDP不是面向連線的,不存在建立連線,釋放連線,每個資料包都是獨立的包,有邊界,一般不會合並。
TCP保證資料正確性,UDP可能丟包,TCP保證資料順序,UDP不保證
8.
const的含義及實現機制,比如:const int i,是怎麼做到i只可讀的?
const指示物件為常量,只讀。
實現機制:這些在編譯期間完成,對於內建型別,如int, 編譯器可能使用常數直接替換掉對此變數的引用。而對於結構體不一定。
看下面的例子:

const int j=100;    int *p=const_cast<int*>(&j);    *p=200;    cout<<j<<endl;    輸出為什麼是100呢?

cout<<*p<<endl; //輸出是改過的200

編譯器在優化程式碼時把cout<<j直接優化成cout<<100了,所以雖然p和&j的值一樣,但cout<<j不再通過訪問j的地址輸出。(反彙編時也有看到直接把數字壓棧push 100 )

這是因為,const型在壓棧時,是使用的直接的數,就有點像C的#define a 100

對於非系統預設型別,系統不知道怎麼去直接替換,因此必須佔據記憶體。

#include <iostream> using namespace std; struct A {    int i;    char ch;    A()    {        i = 100;        ch = ‘S’;    } }; int main() {    const A a;    const int i = 200;    int *p1 = (int*)&a.i;    int *p2 = (int*)&i;    *p1 = 1;    *p2 = 2; //   a.i = 200; //報錯,左值不能為const    cout << a.i << ” ” << a.ch << endl;    cout << i << endl;    return 0; }

執行結果:

1 S 200
9.volatile的含義。
變數可能在編譯器的控制或監控之外改變,告訴編譯器不要優化該變數,如被系統時鐘更新的變數。
10.OFFSETOF(s, m)的巨集定義,s是結構型別,m是s的成員,求m在s中的偏移量。
#define OFFSETOF(s, m) size_t(&((s*)0)->m)
11.100億個數,求最大的1萬個數,並說出演算法的時間複雜度。
小根堆來實現。注意是小根堆,
讀入1萬個數,然後做
時間複雜度是O(NlogK)
12.設計一個洗牌的演算法,並說出演算法的時間複雜度。
第一種: for i:=1 to n do swap(a[i], a[random(1,n)]);  // 湊合,但不是真正隨機
第二種: for i:=1 to n do swap(a[i], a[random(i,n)]);   // 真正的隨機演算法
其中,random(a,b)函式用於返回一個從a到b(包括a和b)的隨機整數。
至於怎麼證明上兩個演算法,沒想好。
演算法複雜度是O(n。。。),要研究下random的實現。
13.socket在什麼情況下可讀?
1. 接收緩衝區有資料,一定可讀 2. 對方正常關閉socket,也是可讀 3. 對於偵聽socket,有新連線到達也可讀
4.socket有錯誤發生,且pending~~~
引用unp的一段話 第六章 6.3節   
A socket is ready for reading if any of the following four conditions is true:
a. The number of bytes of data in the socket receive buffer is greater than or 
     equal to the current size of the low-water mark for the socket receive buffer.
     A read operation on the socket will not block and will return a value greater than 0
b.  The read half of the connections is closed (i.e., A TCP connection that has received a FIN).
     A read operation on the socket will not block and will return 0 (i.e., EOF)
c. The socket is a listening socket and the number of completed connection is nonzero. 
    An accept on the listening socket will normally not block, although we will describe a   
d. A socket error is pending. A read operation on the socket will not block and will return
    an error (-1) with errno set to the specific error condition
14.流量控制與擁塞控制的區別,節點計算機怎樣感知網路擁塞了???
擁塞控制是把整體看成一個處理物件的,流量控制是對單個的節點。
感知的手段應該不少,比如在TCP協議裡,TCP報文的重傳本身就可以作為擁塞的依據。依據這樣的原理, 應該可以設計出很多手段。
15.C++虛擬函式是如何實現的???
使用虛擬函式表。 C++物件使用虛表, 如果是基類的例項,對應位置存放的是基類的函式指標;如果是繼承類,對應位置存放的是繼承類的函式指標(如果在繼承類有實現)。所以 ,當使用基類指標呼叫物件方法時,也會根據具體的例項,呼叫到繼承類的方法。 
16.C++的虛擬函式有什麼作用? ??
虛擬函式作用是實現多型,
更重要的,虛擬函式其實是實現封裝,使得使用者不需要關心實現的細節。
在很多設計模式中都是這樣用法,例如Factory、Bridge、Strategy模式。 
17. 非阻塞connect()如何實現? ??
將socket設定成non-blocking,操作方法同非阻塞read()、write();
18. 以下程式碼輸出結果:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
printf("call execl"); 
sleep(1); 
execl("/bin/sh", "", NULL); 
printf("error!\n");
}
本題考標準IO緩衝,標準出錯是不帶緩緩衝的。

如若是涉及終端裝置的其他流,則他們是行緩衝的;否則是全緩衝的。

printf是標準IO的一個,格式化列印到標準輸出,在這裡是行緩衝,那麼沒有遇到換行符也就是‘\n’或者沒有強制flush, 則不會輸出。 execl是建立新的可執行程式映像,一旦成功就不會返回了,只有在出錯的情況會返回1. 所以以上的程式沒有列印printf的內容,直接執行/bin/sh,輸出為 $ 若是程式碼改為以下: #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) {     printf(“call execl\n”);     /*fprintf(stderr, “%s”, “call execl”);*/     sleep(1);     execl(“/bin/sh”, “”, NULL);     printf(“error!\n”);     return 0; } 則輸出為: call execl $ 若改為: #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) {     /*printf(“call execl\n”);*/     fprintf(stderr, “%s”, “call execl”);       // 標準錯誤,不緩衝     sleep(1);     execl(“/bin/sh”, “”, NULL);     printf(“error!\n”);     return 0; } 則輸出為: call execl$ 若改為: #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) {     /*printf(“call execl\n”);*/     fprintf(stdout, “%s”, “call execl”);     // stdout行緩衝     sleep(1);     execl(“/bin/sh”, “”, NULL);     printf(“error!\n”);     return 0; } 則輸出為 $ 19. TCP通訊中,select到讀事件,但是讀到的資料量是0,為什麼,如何解決???? select 返回0代表超時。select出錯返回-1。 select到讀事件,但是讀到的資料量為0,說明對方已經關閉了socket的讀端。本端關閉讀即可。 當select出錯時,會將介面置為可讀又可寫。這時就要通過判斷select的返回值為-1來區分。 20. 給出float與“零值”比較的 if 語句(假設變數名為var)??? const float EPSINON = 0.00001;
  if ((x >= - EPSINON) && (x <= EPSINON)
浮點數在記憶體中的存貯機制和整型數不同,有舍入誤差在計算機中用以近似表示任意某個實數。具體的說,這個實數由一個整數或定點數(即尾數)乘以某個基數(計算機中通常是2)的整數次冪得到,這種表示方法類似於基數為10的科學記數法。
  所以浮點數在運算過成功運算通常伴隨著因為無法精確表示而進行的近似或舍入。但是這種設計的好處是可以在固定的長度上儲存更大範圍的數。
  例如,一個指數範圍為±4的4位十進位制浮點數可以用來表示43210,4.321或0.0004321,但是沒有足夠的精度來表示432.123和43212.3(必須近似為432.1和43210)。當然,實際使用的位數通常遠大於4。  
  所以浮點數不能夠判斷相等像 if(x==0)的這樣的編碼是不總是正確的,我們在判斷浮點數相等時,推薦用範圍來確定,若x在某一範圍內,我們就認為相等,至於範圍怎麼定義,要看實際情況而已了,float,和double 各有不同
  所以const float EPSINON = 0.00001;  
  if ((x >= - EPSINON) && (x <= EPSINON) 這樣判斷是可取的
  至於為什麼取0.00001,可以自己按實際情況定義