字節跳動 客戶端開發 實習 一面(50min)
- 自我介紹
- 是否愿意轉語言,是否只愿意搞后端
- 選一個項目來詳細談談
- HTTP和HTTPS有什么區別?
- 談一下HTTPS加密的具體過程:
?? ?非對稱加密 + 對稱加密 + 證書認證的方式
?? ??? ?非對稱加密是為了保證對稱密鑰的安全性。
?? ??? ?對稱密鑰是為了保證通信的高效安全。
?? ??? ?證書認證是為了保證非對稱密鑰的合法性。1、首先呢,客戶端先向服務端發送加密通信(https)請求,這次請求中包括:
SSL/TSL版本號
加密套件,也就是客戶端支持的加密算法列表
產生一個隨機數,我們叫他為第1隨機數
有一個Client Hello字符串
2、服務器收到請求后,向客戶端發出響應:
確認SSL/TSL版本號,如果客戶端不支持,那么就關閉通信
確認的加密算法列表
生成一個隨機數,我們叫第2隨機數
3、服務器再向客戶端發送數字證書,這里敲重點了。服務器會把自己的公鑰注冊到CA(第三方證書機構),然后CA拿自己的私鑰對服務器的公鑰進行處理并頒發數字證書。
4、服務器將公鑰發送給客戶端
5、服務器發送Hello Done,表示發送完畢
6、客戶端收到服務端一系列響應后,確認數字證書和公鑰,沒有問題后向服務端發送:
生成一個隨機數,我們叫第3隨機數或者預主密鑰,此預主密鑰會通過公鑰進行加密
客戶端握手結束通知,表示客戶端的握手結束
7、服務端收到客戶端數據后,使用私鑰對加密后的預主密鑰進行解密,沒有其他人知道預主密鑰,因為它加密了,除非服務器私鑰泄漏。然后服務端通過第一、二、預主密鑰計算出會話密鑰。客戶端也計算出了會話密鑰。
8、服務端向客戶端發送:
加密通信算法改變通知,以后通過會話密鑰通信
服務端握手結束
到此為止,SSL/TSL握手結束,在此之后都會通過會話密鑰來進行加密和解密,也就是對稱加密。- 談一下在瀏覽器輸入一段url后獲取資源的全過程
? ? ? ? ?DNS查詢
?? ??? ??TCP連接
?? ??? ??發送HTTP請求
?? ??? ??服務器處理HTTP請求并返回HTTP報文
?? ??? ??瀏覽器解析并render頁面
?? ??? ??HTTP連接斷開瀏覽器輸入url后經歷的過程(詳細)_瀏覽器輸入一個url的全過程-CSDN博客
- 了解過瀏覽器的渲染沒有?
- 講一下TCP和UDP的區別?
- 講一下三次握手的具體過程?
- 為什么是四次揮手?三次行不行?
? ? ? ? TCP連接是全雙工通信的,而斷開時雙方都需要確定兩個問題:自己是否還有數據要發送,對端是否還有數據要發送,而四次揮手正好在雙方同步了這兩個問題。
第一次揮手:client告訴server自己的數據已全部發送,client可以回收發送緩沖區,server可以回收接收緩沖區
第二次揮手:server告訴client自己收到了關閉信息
第三次揮手:server告訴client自己的數據已全部發送,server可以回收發送緩沖區,client可以回收接收緩沖區
第四次揮手:client告訴server自己收到了關閉信息- 進程和線程的區別?
- 用什么方式實現線程同步?
- 使用過哪些進程間通信的方式?
- 手撕單例模式
- 反問環節
騰訊QQ部門C++一面(實習)
- 在C語言中定義一個全局變量,但不初始化,它默認的值是多少?該類型的“零值”,一般為0或者NULL
- -2的源碼,反碼,補碼分別是什么?-3呢?它的公式是什么?原碼:二進制最高位為1,反碼:除了符號位全部取反,補碼:原碼+1
- 一個數組有n個元素,找到前k個最大的(一切你能想到的辦法)
方法1:排序,快排或,堆排降序,前N個就是最大的。上篇學過時間復雜度: O(N*logN)
方法2:N個數依次插入大堆,HeapPop?K次,每次取堆頂的數據,即為前K個。
時間復雜度: O(K*logN)? ? ? ? ? ? ?
假設 N非常大, 是 10 億,內存中存不下這些數,它們存在文件中的。 K是 100,
上面的方法就都不能用了……
話說 10 億個整數,大概占用多少空間?
1G = 1024MB
1G = 1024*1024KB
1G = 1024*1024*1024Byte
要占用10億字節!所以我們來看看方法3:方法3:
- 簡歷上寫了雙指針和二分查找算法,能否具體講一下思路?
? ? ? ? ? ?雙指針算法是一種處理線性結構的有效方法,它利用了兩個指針分別位于序列的不同位置,通過它們之間的移動來實現問題的求解或滿足特定的條件。這種算法的核心思想是利用指針的移動來逐步縮小待解決問題的規模。雙指針算法可以應用于任何包含順序存儲的線性數據結構中,特別是那些可以進行適當并行處理的場景。
? ? ? ? ?具體來說,雙指針算法涉及以下步驟:
? ? ? ? ? 初始化:創建兩個指針,一個用于遍歷序列的前半部分,另一個用于遍歷序列的后半部分。這兩個指針通常初始化為序列的起始和末尾位置。
? ? ? ? ?移動指針:重復執行以下操作之一,直至找到所需的解決方案或其他終止條件:
同時移動兩個指針相同的步長;
? ? ? ? ?一個指針后移,另一個指針前移相同的步長;
? ? ? ? ? 兩個指針交替前進,使得每次只有一個指針改變其當前位置。
? ? ? ? ?停止條件:當兩個指針相遇(即到達同一位置),或者達到預設的條件時,算法結束并返回結果。? ? ? ? 雙指針算法的一個關鍵優勢在于它可以充分利用數組的有序性,這可能導致某些計算變得更加簡單,從而降低時間復雜度。在一些情況下,雙指針算法可以將時間復雜度從O(N^2)降低到O(N),尤其是當指針的移動是基于數組已排序的信息時。
? ? ? ? ? ? ? ? 二分查找一種效率較高的查找方法。已經有嚴謹的數學證明其時間復雜度是O(logN),如果在全國14億人口中找一個人,那么只需查找31次,但是,二分查找要求線性表必須采用順序存儲結構,而且表中元素按關鍵字有序排列(無序有時也行,但是要有二段性)。一般步驟如下:
? ? ? ? 首先,假設表中元素是按升序排列,將表中間位置記錄的關鍵字與查找關鍵字比較,如果兩者相等,則查找成功;否則利用中間位置記錄將表分成前、后兩個子表,如果中間位置記錄的關鍵字大于查找關鍵字,則進一步查找前一子表,否則進一步查找后一子表。重復以上過程,直到找到滿足條件的記錄,使查找成功,或直到子表不存在為止,此時查找不成功。
- Linux中是怎樣用C語言實現面向對象的封裝,繼承,多態的?(這個問題沒聽懂)
向對象的三大特性為:封裝、繼承、多態。如果用C語言來實現OOP編程方式,就需要從這三個特性入手:
封裝
在C語言中沒有類和對象這種語法,但這并不影響我們使用類和對象的概念。我們可以使用結構體來實現類,而該結構體變量就是對象。封裝描述的是數據的組織形式,就是把屬于一個對象的所有屬性(數據)組織在一起,C語言中的結構體類型天生就支持這一點。繼承
繼承描述的是對象之間的關系,子類通過繼承父類,自動擁有父類中的屬性和行為(也就是方法)。這個問題只要理解了C語言的內存模型,也不是問題,只要在子類結構體中的第一個成員變量的位置放置一個父類結構體變量,那么子類對象就繼承了父類中的屬性。多態
多態指同一個接口的多種實現方式,是面向對象的核心。在執行過程中,可執行程序根據執行對象的不同,展現不同的行為。多態的存在,使得同樣的代碼,可以展現出不同的特性,這也是多態最引人入勝的地方。模擬多態可以在基類的函數方法中,通過獲取子類對象,再嵌套調用子類的同名函數來實- C++中的class和C語言中的struct有什么區別?
C的結構體中不允許有函數的存在,C++的結構體允許有內部成員函數,并且允許該函數是虛函數。
C的結構體內部成員不能加權限,默認是public;而C++ 的結構體內部成員權限和class一樣,可以是private、protected、public,且 默認是public。
C的結構體不可以繼承,C++的結構體可以從其他的結構體或者類繼承。
C的結構體不能對數據成員初始化,C++可以。C中使用結構體需要加上struct關鍵字,或者對結構體用typedef取別名后使用;而C++中可以直接使用結構體名來聲明對象? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??struct和class區別
struct一般用于描述一個數據的集合;class是對一個對象數據的封裝。
struct默認訪問權限是public;class默認訪問控制權限是private。
在繼承關系中,struct默認是公有繼承;class默認是私有繼承。
class關鍵字可以用于定義模板參數;struct不可以。示例:- UDP數據包的最大長度是多少?為什么?(之前刷騰訊面經看見過)
? ? ? udp數據包的理論長度是多少,合適的udp數據包應該是多少呢?從TCP-IP詳解卷一第11章的udp數據包的包頭可以看出,udp的最大包長度是2^16-1的個字節。由于udp包頭占8個字節,而在ip層進行封裝后的ip包頭占去20字節,所以這個是udp數據包的最大理論長度是2^16-1-8-20=65507。
? ? ? ? ? 然而這個只是udp數據包的最大理論長度。首先,我們知道,TCP/IP通常被認為是一個四層協議系統,包括鏈路層、網絡層、運輸層、應用層。UDP屬于運輸層,在傳輸過程中,udp包的整體是作為下層協議的數據字段進行傳輸的,它的長度大小受到下層ip層和數據鏈路層協議的制約。
? ? ? ? ? ? ?以太網(Ethernet)數據幀的長度必須在46-1500字節之間,這是由以太網的物理特性決定的。這個1500字節被稱為鏈路層的MTU(最大傳輸單元).
? ? ? ? ? 但這并不是指鏈路層的長度被限制在1500字節,其實這這個MTU指的是鏈路層的數據區.并不包括鏈路層的首部和尾部的18個字節.
? ? ? ? ?所以,事實上,這個1500字節就是網絡層IP數據報的長度限制.因為IP數據報的首部為20字節,所以IP數據報的數據區長度最大為1480字節。而這個1480字節就是用來放TCP傳來的TCP報文段或UDP傳來的UDP數據報的。又因為UDP數據報的首部8字節,所以UDP數據報的數據區最大長度為1472字節。這個1472字節就是我們可以使用的字節數。- TCP通信中,read函數的返回值返回0代表什么情況?連接關閉:返回0表示對方已經關閉了連接。在TCP通信中,當對方關閉連接時,read函數會返回0,表示沒有更多的數據可讀取
static void service(int sock, const std::string &clientip,const uint16_t &clientport, const std::string &thread_name) // 帶上線程名的service {// echo serverchar buffer[1024];while (true){// read && write 可以直接被使用ssize_t s = read(sock, buffer, sizeof(buffer) - 1);if (s > 0){buffer[s] = 0; // 將發過來的數據當做字符串std::cout << thread_name << "|" << clientip << ":" << clientport << "# " << buffer << std::endl;}else if (s == 0) // 對端關閉連接{logMessage(NORMAL, "%s:%d shutdown, me too", clientip.c_str(), clientport);break;}else{logMessage(ERROR, "read socket error, %d:%s", errno, strerror(errno));break;}write(sock, buffer, strlen(buffer));}close(sock); }
- 寫一個while(1)的死循環,一直使用malloc申請空間,程序會崩潰嗎?
? ? ? ? ?在C語言中,編寫一個`while(1)`的死循環并不斷使用`malloc`申請空間,程序本身不會崩潰。這是因為`malloc`函數用于動態內存分配,每次調用`malloc`都會從堆中分配指定大小的內存空間,并返回指向該空間的指針。只要系統有足夠的內存資源,這個過程可以無限進行下去,不會導致程序崩潰。
? ? ? ? 然而,需要注意的是,如果系統內存資源有限,不斷申請內存最終會導致內存耗盡。當可用內存不足以滿足`malloc`的請求時,`malloc`會返回`NULL`指針,并且可能會觸發程序的其他錯誤處理邏輯。此外,如果程序中沒有相應的`free`調用來釋放不再使用的內存空間,最終會導致內存泄漏,這可能會對程序的長期運行產生負面影響。
? ? ? ? ?總結來說,一個不斷使用`malloc`申請空間的`while(1)`死循環本身不會導致程序崩潰,但可能會因為內存耗盡或內存泄漏而影響程序的正常運行
- 進程退出時,假設存在沒有釋放的資源,此時應該怎樣做?(進程死的時候,肯定是資源皆被內核釋放的)
- 你使用過這個項目和谷歌的TCmalloc項目做過對比嗎?
- 項目中是怎樣實現減少內碎片和外碎片問題的?
- 項目中如果用戶忘記釋放內存或多次釋放內存,你有沒有做特殊處理?
總的來說,問的東西不是一些簡單的概念,需要對目標足夠熟悉才能回答上來
網易雷火 服務端開發一面(C++實習)
- 前綴表達式求值(+-*2 3 5/…^2 4 6 =?)
- 看代碼的選擇題(關于整數和字符相加,%c打印整數,%d打印字符的問題)
- 關于大小端的選擇題,(包括X86系統下是大端還是小端?)
- 構造函數可以是虛函數嗎?析構函數呢?
- new/delete和malloc/free的區別?
- malloc申請100字節大小和申請100MB大小有什么區別?brk和mmap
- 函數參數在棧上的壓棧順序是什么?函數中的局部變量呢?(函數棧幀的內容)
? ? ? ? ? ?在C++中,函數參數和局部變量都是在棧上進行內存分配的。函數參數的壓棧順序是從右到左,也就是說,最右邊的參數首先被壓入棧中,然后是次右邊的參數,以此類推,最后是最左邊的參數。
? ? ? ? ? 例如,對于函數調用
func(a, b, c)
,參數c
會首先被壓入棧中,然后是參數b
,最后是參數a
。? ? ? ? ? 對于函數中的局部變量,它們的內存分配也是在棧上進行的。當函數被調用時,局部變量會在棧上分配內存空間,并在函數執行完畢后自動釋放。局部變量的分配順序與其在函數中的聲明順序一致。
- 在函數中創建數組:int a[100000000000000];會有什么問題嗎?(我答的棧溢出)
- 什么是大小端?你怎樣判斷當前機器是大端還是小端?
int check_sys() {//小端:00 00 00 01 ?大端01 00 00 00(內存中的數據是以十六進制存儲的)int i = 1;//強轉成(char *),訪問一個字節的地址,再解引用(*)取值得到起始一個地址的內容//若為大端則取00返回,小端則返回01(即1);return (*(char *)&i); } int check_sys() {union{int i;char c;}un;un.i = 1;return un.c; }
- 怎樣判斷一個編譯器的棧區是從下到上增長還是從上到下增長的?
? ? ? ? ? ? 畢竟堆棧也就是內存,自然就可以通過堆棧的分配過程取出所分配的內存地址來比較判斷,而C語言可以方便的訪問內存,也就比較容易判斷當前處理器中堆棧指針的增長方向了。
? ? ? ? ? ?那還不簡單,直接在函數內部先后定義兩個局部變量,直接比較兩個變量的地址大小不就搞定了嗎?其實這種方式是依賴于編譯器實現的,畢竟哪個變量先進行內存申請,并沒有太大的影響。
那么是否有一種方法不依賴于編譯器實現呢?
必須有的,那就是函數調用棧了,因為先調用的函數必然首先入棧。
- 用static修飾局部變量會發生什么?這個變量還在棧上嗎?static修飾局部變量使得變量的存儲位置發生了變化,本來局部變量是放在棧區的,被static修飾后,放在內存的靜態區,生命周期變得更長了,但是作用域沒有發生變化。
- Linux中,怎樣快速在tmp.log日志文件中查找到error字段?
在Linux中,你可以使用grep命令來快速在文件中查找指定的字段。對于你的需求,可以使用以下命令來在tmp.log日志文件中查找error字段:
```
grep "error" tmp.log
```這個命令會在tmp.log文件中查找包含"error"字段的行,并將結果輸出到終端上。如果你想要忽略大小寫,可以加上-i參數:
```
grep -i "error" tmp.log
```如果你想要同時查找多個關鍵字,可以使用grep的正則表達式功能。例如,要查找同時包含"error"和"warning"字段的行,可以使用以下命令:
```
grep -E "error|warning" tmp.log
```這個命令使用了-E參數來啟用正則表達式模式,并使用豎線符號(|)來表示邏輯或關系。
- 一個進程被異常終止后,怎樣快速找到出錯的地方?出錯的常見原因?
當一個進程被異常終止后,可以通過以下幾種方式來快速找到出錯的地方:
1. 日志記錄:進程在運行過程中可以將關鍵信息記錄到日志文件中。當進程異常終止時,可以查看日志文件,根據錯誤信息定位到出錯的地方。
2. 棧回溯:在異常終止時,進程會生成一個錯誤堆棧(stack trace),其中包含了函數調用的層次關系。通過分析堆棧信息,可以追蹤到出錯的具體函數和代碼行數。
3. 調試工具:使用調試工具可以對進程進行調試,例如使用斷點、單步執行等功能。在進程異常終止時,可以通過調試工具查看當前執行的代碼位置,以及變量的值,從而找到出錯的地方。
常見的進程異常終止的原因包括:
1. 內存錯誤:例如訪問了未分配的內存、訪問越界等。這可能導致進程崩潰或產生未定義行為。
2. 空指針引用:當程序中使用了空指針進行操作時,會導致進程異常終止。
3. 死鎖:多線程或多進程程序中,如果存在資源競爭或者同步問題,可能導致死鎖現象,進而導致進程異常終止。
4. 文件操作錯誤:例如打開不存在的文件、權限不足等,可能導致進程異常終止。
5. 系統調用錯誤:當進程調用系統提供的接口時,如果參數錯誤或者系統狀態異常,可能導致進程異常終止。
- 在gdb調試中,如何從當前函數的棧幀跳躍到其他函數的棧幀?
使用backtrace命令(簡寫為bt)查看當前函數的棧幀和調用鏈,找到目標函數的棧幀地址。
使用frame命令(簡寫為f)加上目標函數的棧幀編號,可以切換到目標函數的棧幀。例如,使用f 3命令可以跳轉到第三個棧幀。
使用info frame命令(簡寫為i frame)可以查看當前棧幀的詳細信息,包括函數名稱、參數、局部變量等。這些信息可以幫助你確認是否已經切換到了目標函數的棧幀。
使用up命令可以向上切換到上一層棧幀,即調用當前函數的函數的棧幀。
使用down命令可以向下切換到下一層棧幀,即被當前函數調用的函數的棧幀。
- 在析構函數中寫delete this可以嗎?在類中的其他函數中寫呢?
? ? ? ?在析構函數中寫 delete this 是合法的操作,但是需要非常小心使用。這種操作被稱為自刪除(self-deletion),它會導致當前對象在析構函數執行完畢后被刪除。這意味著在 delete this 之后,不應再訪問或使用當前對象的任何成員或方法,因為它們已經無效。自刪除的常見用例是在對象完成自身資源清理后,進行自動銷毀。
? ? ? ?在類的其他函數中寫 delete this 是不安全的,因為這樣會導致正在執行的函數在被刪除的對象上繼續執行,從而引發未定義行為。除非你非常清楚自己在做什么,并確保在調用 delete this 之后不再使用當前對象,否則會導致潛在的錯誤和不可預測的行為。
- 將A端的結構體數據通過網絡發送至b端,需要注意什么問題?
序列化和反序列化:結構體數據在網絡傳輸前需要進行序列化,即將結構體轉化為字節流,以便在網絡上傳輸。在端B接收到數據后,需要對接收到的字節流進行反序列化,將其還原為結構體。確保在序列化和反序列化過程中,數據的格式和順序保持一致。
網絡字節順序:不同的機器和操作系統可能有不同的字節順序(大端序或小端序),因此在發送和接收數據時,需要確保統一使用網絡字節順序(一般為大端序)。
結構體布局和對齊:結構體的成員在內存中的布局和對齊可能在不同的編譯器和平臺上有所不同。為了確保數據的準確傳輸,需要在發送和接收端對結構體進行適當的對齊和填充,以避免數據錯位或內存對齊的問題。
數據大小和邊界檢查:確保傳輸的數據大小不超過網絡協議的限制,避免數據丟失或截斷。此外,還需要在接收端對接收到的數據進行邊界檢查,防止緩沖區溢出等安全問題。
錯誤處理和容錯機制:在網絡傳輸過程中,可能會出現連接中斷、數據丟失或傳輸錯誤等問題。為了確保可靠的數據傳輸,需要實現適當的錯誤處理和容錯機制,如重傳機制、校驗和校驗等。
數據加密和安全性:如果傳輸的結構體數據包含敏感信息,建議在傳輸過程中進行加密,確保數據的安全性和保密性。
網絡延遲和帶寬:在網絡傳輸過程中,要考慮網絡延遲和帶寬的限制。對于大型結構體數據或需要實時性較高的場景,可能需要采取數據壓縮、流控制等優化措施。
- 了解過哪些序列化/反序列化的方式?除了這些方式能不能現場想一個?
?雖然序列化和反序列化可以自己實現,但是非常麻煩,有一些現成的工具可以直接進行序列化和反序列化,如:
Json:使用簡單。
protobu:比較復雜,局域網或者本地網絡通信使用較多。
xml:其他編程語言使用(如Java等)。Json序列化和反序列化
約定方案一:
客戶端發送一個形如"1+1"的字符串
這個字符串中有兩個操作數,都是整形
兩個數字之間會有一個字符是運算符
運算符只能是加減乘除和取模
數字和運算符之間沒有空格? ? ? ? ? ? ? ? ? ? ? ?約定方案二:
定義結構體來表示我們需要交互的信息
發送數據時將這個結構體按照一個規則轉換成字符串
接收到數據的時候再按照相同的規則把字符串轉化回結構體
這個過程叫做 "序列化" 和 "反序列化- 能不能想一些辦法來解決UDP丟包的問題?(我感覺把TCP的內些方案說出來吧)
使用確認機制:在應用層實現確認機制,即接收方收到數據后向發送方發送確認消息。發送方在一定時間內未收到確認消息,即認為數據丟失,并進行重傳。
設置超時重傳機制:發送方在發送數據后,設置一個超時計時器。如果超過設定的時間還未收到確認消息,就進行重傳。
使用冗余校驗:發送方可以在數據包中添加冗余校驗信息,如校驗和或循環冗余校驗(CRC)。接收方對接收到的數據進行校驗,如果校驗失敗,則要求重新發送。
數據分片和重組:將大的數據包分片發送,接收方在接收到分片后進行重組。如果某個分片丟失,可以要求發送方重新發送該分片。
前向糾錯(Forward Error Correction,FEC):發送方在發送數據時添加一些冗余數據,接收方可以使用這些冗余數據進行糾錯,從而在一定程度上恢復丟失的數據。
組播和廣播:對于實時性較高、丟包容忍度較低的場景,可以考慮使用組播或廣播方式,通過多個接收方接收數據,提高數據傳輸的可靠性。
流量控制和擁塞控制:使用流量控制和擁塞控制機制,避免網絡擁塞,減少丟包的可能性。
應用層重傳:在應用層實現重傳機制,記錄已發送的數據和未收到確認的數據,在一定時間后進行重傳。
- socket套接字編程的一般流程?使用過shutdown/close函數嗎?
創建Socket:使用socket()函數創建一個套接字,指定協議族(如IPv4或IPv6)和套接字類型(如TCP或UDP)。
綁定地址:對于服務器端,使用bind()函數將套接字綁定到一個特定的IP地址和端口號。對于客戶端,可以選擇性地綁定本地地址。
監聽連接(對于服務器端):對于TCP服務器,調用listen()函數開始監聽連接請求。指定監聽隊列長度,即等待接受連接的最大數量。
接受連接(對于服務器端):使用accept()函數接受客戶端的連接請求,創建一個新的套接字用于與客戶端通信。可以在循環中接受多個連接。
連接服務器(對于客戶端):對于TCP客戶端,使用connect()函數連接到服務器的IP地址和端口號。
數據傳輸:連接建立后,使用send()函數發送數據或者recv()函數接收數據。使用write()和read()函數也可以進行數據傳輸。
關閉連接:使用close()函數關閉連接的套接字。
? ? 在以上流程中,服務器端和客戶端的流程略有不同。服務器端需要創建套接字、綁定地址、監聽連接、接受連接和進行數據傳輸。而客戶端需要創建套接字、連接服務器和進行數據傳輸。具體的實現細節和操作順序可能會因編程語言和具體需求而有所不同。
? ? ? 此外,在實際開發中,還需要處理錯誤和異常情況,進行適當的錯誤處理、超時設置、線程或進程管理等。
- 一款賽車游戲,用一次策略判斷賽車手的名次高低?(直線/圓形/S型賽道?)
總的來說,問的很深,并且面試官很在乎我的思考過程,很多問題都是不重結果,是重思考
快手C++研發一面(實習,70分鐘)
C++11的特性都了解過哪些?
介紹一下有哪些智能指針?
介紹一下lambda表達式有幾種捕捉的方式?
捕捉列表描述了上下文中哪些數據可以被lambda使用,以及使用的方式是傳值還是傳引用。
[var]:表示值傳遞方式捕捉變量var
[=]:表示值傳遞方式捕獲所有父作用域中的變量(包括this)
[&var]:表示引用傳遞捕捉變量var,捕捉,不是傳參,捕捉中就不存在取地址這一語法。
[&]:表示引用傳遞捕捉所有父作用域中的變量(包括this)平時用過右值引用嗎? 實際項目中常用嗎?
手撕算法題: K個一組翻轉鏈表(力扣25題,hard),能不能用兩種方法解決?(占比時間最多,面試官不僅在考察我的代碼和算法能力,還在考察我debug下測試代碼的經驗,面試官全程和我一起改bug)每日OJ題_鏈表⑤_力扣25. K 個一組翻轉鏈表-CSDN博客
場景題:象棋中的馬一次可以跳一個日字形(不考慮絆腳),假設棋盤無限大,且棋盤中有障礙物(馬不能跳到障礙物上),馬從(0,0)位置開始要跳到(m,n)位置,怎樣計算最小的跳躍次數? (我想的是廣度優先遍歷),面試官再問: 有沒有什么方法可以優化一下時間或者空間?
整個面試過程非常輕松,面試官人很好,在引領我去思考他心中的答案
最后反問面試官,希望在實習生身上看見什么樣的特質? 他說有基礎,夠聰明就行,要求不高
萬集科技一面 軟件
自我介紹
介紹一下你簡歷中的兩個項目
然后接下來的十幾分鐘時間全在問項目相關的問題
說一下TCP和UDP
講一下粘包,TCP和UDP哪個會有粘包問題,怎么解決
? ? ? ? 在TCP的協議頭中,沒有如同UDP一樣的 “報文長度” 這樣的字段,但是有一個32位序號的字段。站在傳輸層的角度,TCP是一個一個數據段過來的,按照序號排好序放在緩沖區中。
? ? ? ? 站在應用層的角度,看到的只是一串連續的字節數據,那么應用程序看到了這么一連串的字節數據,就不知道從哪個部分開始到哪個部分,是一個完整的應用層數據包,此時應用層在讀取數據的時候就會產生粘包問題,可能讀取的不是一個完整報文,也可能是一個半報文等等情況。
? ? ? ? 粘包的問題是指不同報文一起發送到網絡上,則當寫的緩沖區當中存在不同的報文的時候,就會發生粘包問題。
可能會觸發TCP粘包的情況:
應用程序寫入數據小于套接字緩沖區大小,網卡將應用多次寫入的數據發送到網絡上,這將會發生粘包。
接收方不及時讀取套接字緩沖區數據,這將發生粘包。
解決這個問題,歸根到底就是要明確兩個包之間的邊界。解決粘包問題:
使用短連接來解決TCP粘包的問題。
緩解粘包問題:
? ? ? ? ? 關閉nagle算法能夠緩解TCP粘包問題(nagle算法可以很大程度的利用網絡帶寬,nagle算法其中之一的規則為:如果該包含有FIN,則允許發送)
? ? ? ? 使用帶消息頭的協議、消息頭存儲消息開始標識及消息長度信息,服務端獲取消息頭的時候解析出消息長度,然后向后讀取該長度的內容
設置定長消息,服務端每次讀取既定長度的內容作為一條完整消息,當消息不夠長時,空位補上固定字符
? ? ? ? 在之前博客的協議定制中,采用的是TCP協議,在應用層讀取接收緩沖區數據的時候,通過用戶層代碼來保證每次讀取到的是一個完整報文。? ? ? ? 每個報文都有一個報頭,報頭中的內容就是有效載荷的長度,這是由程序員定義的用戶層協議。
對于UDP協議來說,就不存在粘包問題:
? ? ? ? 如果還沒有上層交付數據,UDP的報文長度仍然在在首部中。同時,UDP是一個一個把數據報交付給應用層就有很明確的數據邊界。 站在應用層的站在應用層的角度,使用UDP的時候,要么收到完整的UDP報文,要么不收,不會出現"半個"的情況
除了TCP和UDP,你還學過其他的通信協議嗎TCP/IP協議、UDP協議、HTTP協議、FTP協議、Telnet協議、SMTP協議、NFS協議等。
你平時用C++的文件操作,用的是哪些函數,參數是什么
C++根據文件內容的數據格式分為二進制文件和文本文件。
采用文件流對象操作文件的一般步驟:
① 定義一個文件流對象 ifstream ifile(只輸入用)ofstream ofile(只輸出用)fstream iofile(既輸入又輸出用)。
② 使用文件流對象的成員函數打開一個磁盤文件,使得文件流對象和磁盤文件之間建立聯系。
③ 使用提取和插入運算符對文件進行讀寫操作,或使用成員函數進行讀寫。
④ 關閉文件。C++文件操作如果給一個配置文件后面追加內容
? ? ? ? ? 在這兩個對象中,ofstream::open或ifstream::open是打開文件的函數,該函數默認以out或in的方式讀入或寫出,這兩種方式都會先清空文件中的數據,如果想在上一次執行該操作的文件后加入數據,那么就要用ios類中的app方法,ios:app
ios::app:打開文件不會清空數據,文件指針始終在文件尾,因此只能在文件尾寫數據。
學過redis嗎? 沒有
你自己寫過那些多線程之間的那些通信方法嗎(好像是這么問的)
講一下大端和小端
總結:大端模式,低位放在高地址,高位放在低地址
總結:小端模式,低位放在低地址,高位放在高地址
#include<stdio.h> int check_sys() {int i = 1;char* p = (char*)&i; // 取第一個字節return *p; // 返回1表示小端(01 00 00 00),返回0表示大端(00 00 00 01) } int main() {if (check_sys){printf("小端\n");}else{printf("大端\n");}return 0; } /*為什么會有大小端模式之分呢?這是因為在 計算機系統中,是以字節為單位的, 每個地址單元都對應著一 個字節,一個字節為8bit。但是在C語言中除了8bit的char之外, 還有16bit的short型,32bit的long型(要看具體的編譯器),另外,對于位數大于8位的處理器,例如16位或者32位的處理器,由于寄存器寬度大于一個字節, 那么 必然存在著一個如何將多個字節安排的問題。正是因為 不同的安排順序導致了 大端存儲模式和 小端存儲模式的存在。*/
你覺得應聘我們這個崗位有什么優勢
誠邁科技-安卓hal層開發-一二面
1.C語言和C++以及JAVA的區別
2.說一說面向對象是什么?
2.排序中你最熟悉的排序是什么?
3.了解安卓hal層開發嗎?
二面:
1.static關鍵字的作用聲明為?static?的類成員稱為類的靜態成員,用?static?修飾的成員變量,稱為靜態成員變量。
用?static?修飾的成員函數,稱為靜態成員函數,靜態的成員變量一定要在類外進行初始化。
① 靜態成員為所有類對象所共享,不屬于某個具體的實例。
② 靜態成員變量必須在類外定義,定義時不添加 static 關鍵字。
③ 類靜態成員即可用類名 :: 靜態成員變量或者對象 . 來訪問。
如果它是公有的,我們就可以在類外對它進行訪問:
2.說一說五種IO模型
3.高性能服務器編程的模塊有什么,用到了哪些系統調用
騰訊PC客戶端一面(實習,1h)
- 自我介紹
- 介紹類的封裝、繼承和多態
- 多態的實現以及底層機制
- 簡單介紹對智能指針的了解
- shared_ptr的底層實現及使用機制
- 簡要描述快排的實現思想以及時間復雜度,極端情況舉例
- 說說TCP的了解,握手過程,可靠傳輸機制如何實現整個過程是怎么樣的
- UDP如何實現可靠傳輸
- TCP粘包問題如何解決
- 出于什么樣的想法,去做這樣的項目,自己有實際落地過嗎
- 說說你了解的設計模式
- 項目中使用的單例模式是線程安全的嗎
問了半小時問題,剩下就是做2道編程題
八股文因為太緊張說得也不行...
然后編程題做得太差,直接就寄了,但是前天做得測評第二天就發面試通知了,可以去試試
百度面經(知識圖譜部)一面
1.自我介紹
介紹完了,打開共享,對著簡歷一點一點問
2.ffmpeg在項目中是怎么使用的
回答了ffmpeg在項目中使用的命令,用來干了什么
3.為什么使用toml配置,了解過yml配置嗎,為什么不用常規的json配置
這個以前沒有任何的面試官注意到這個,也是第一次被問,就現編了
4.項目的并發量上來了怎么辦
回答了分布式的一系列相關(消息隊列、負載均衡、分庫分表等)
得虧之前面騰訊云智的時候被問到了,正好就準備了,不然ji了
5.把文件存在本地,數據量上來了怎么辦
轉存數據庫,如果視頻文件過大,用ffmpeg切片,然后用多線程傳
6.視頻合成會不會遇到什么問題
? ? ? ? 這個是我回答上一個問題時,提到了切片,當去數據庫提取視頻時,必然要合成,恰好面試官之前就遇到了這個合成的不穩定的一個問題,就問了
7.項目的日志是怎么建立的,有沒有對日志進行分類、分期
這個是我的第二個項目搜索引擎,正好前幾天看了webserver的日志實現,就把一些東西也答上去了
8.多進程、多線程的區別
答的不是很好,但最終還是落到點子上了,通信方式的不同
9.redis和MySQL的區別
從存儲、使用方式來答的
10.對什么樣的數據會使用redis
這就就經典了,列舉了一些熱點數據
11.二叉搜索樹的概念、插入、刪除
先講了概念,講到刪除的時候,讓我畫個圖,邊畫邊講
12.有使用過vim編輯器嗎
搜索引擎就是在Linux上開發的,那這個肯定很了解了,還說了遠程連接vscode的開發,面試官也說,他們自己用的是icoding(是vscode的百度版,就是再封裝了一層)
13.在分布式的場景下,MySQL的事務會遇到什么問題,會用到什么鎖,有沒有思路
這個我是真沒有了解過了
這是ai給的答案,就只答了第六點,誒
14.面試官問我有沒有用過文心一言
我回答沒有,一直用的gpt和claude(說完仔細一想這么一搞,不把面試官的工作給否定了嗎),然后就說,因為文心一言畢竟才出的,還有些許bug待調,想等他迭代到一定程度的時候再去使用
說完,面試官就給我展示了,他們內部用的一些接口,很牛逼,可以直接根據文本生成對應的視頻,還子帶語音解說,這可太nice了
代碼題:快樂數(LeetCode202)每日OJ題_算法_雙指針③_力扣202. 快樂數-CSDN博客
直接在vs上寫的題,用的記憶化搜索,不過是在while循環中
都沒有運行,面試官看了大致思路對了,就過了,然后問了幾個極端情況,如果出現一直遞增且數據不重復怎么辦
這個題之前做過,就記得有一組是死循環,現推沒推出來
總結:
這個崗位是可以轉正的,實習滿3個月,聽到面試官說的最多的就是:對的,這點我很開心(感覺面試官還是對我很認可的),面試官基本沒問八股,全是基于項目的場景問題,中間有點小插曲(沒太弄懂共享,一換就調了一段時間)
面試官老有耐心了,無論哪卡殼了,都說慢慢來不著急,搞的我對這個部門很上頭啊。
字節跳動-游戲服務端開發實習生-C++方向
- 1.自我介紹->由于我跨專業也問了為啥學計算機
- 2.C語言面向過程和C++面向對象的區別->為什么有了C語言還要又C++,C語言有什么缺點
- 3.一道多態問答題,類似B類繼承A類,C類繼承B類,A* p = new C;delete p,這種題目過程中的打印問題
- 4.內存頁面置換算法(LRU),問了是否了解其他算法,也詳細詢問了LRU的細節。一般我們置換過程采取的線性遍歷,面試官還問了是否有更快的算法
- 5.MySql的內外鏈接,有什么不同
- 6.MySql的主鍵,唯一鍵的區別,什么是普通索引,為什么要用索引,舉列說明什么場景下用主鍵索引
1. 主鍵 (Primary Key)
主鍵是數據庫表中的一個特殊列或列的組合,用于唯一標識表中的每一行。一個表只能有一個主鍵,并且主鍵列中的值必須是唯一的,不能為空。
2. 唯一鍵 (Unique Key)
唯一鍵也是用于確保表中某列或某幾列的組合具有唯一性。與主鍵不同的是,一個表可以有多個唯一鍵,并且唯一鍵列中的值可以為空(但每個空值必須是唯一的)。
3. 普通索引 (Index)
普通索引是除主鍵和唯一鍵之外的索引,它僅僅是為了提高查詢速度而創建的。普通索引沒有唯一性的限制,可以有多個重復的鍵值。
為什么要用索引?
索引的主要目的是為了加快數據的檢索速度。沒有索引的情況下,數據庫系統必須掃描整個表來找到相關的行,這被稱為全表掃描,對于大型表來說是非常低效的。而有了索引,數據庫系統可以直接定位到存儲數據的具體位置,從而大大提高查詢速度。
具體來說,使用索引的好處包括:
- 提高查詢速度:通過索引,數據庫可以快速地定位到數據,避免全表掃描。
- 加速表的連接:在查詢中涉及多個表時,使用索引可以加速表之間的連接操作。
- 保證數據的唯一性:通過主鍵和唯一鍵索引,可以確保表中數據的唯一性。
- 提高數據檢索的排序速度:索引本身就按照特定的順序存儲數據,因此按照索引的順序檢索數據可以比隨機從磁盤上讀取數據快得多。
需要注意的是,雖然索引可以提高查詢速度,但它也會占用額外的磁盤空間,并且在插入、更新和刪除數據時可能會降低性能,因為索引也需要進行相應的維護。因此,在設計數據庫和索引時需要權衡利弊,根據實際需求來選擇合適的索引策略。
- 7.函數重載和重寫的區別,返回值能區分函數重載嗎
函數重載(Overloading)和函數重寫(Overriding)是面向對象編程中的兩個重要概念,它們各自有特定的用途和規則。下面我將詳細解釋它們之間的區別,并回答返回值是否能區分函數重載的問題。
函數重載(Overloading)
函數重載是指在同一個作用域內,可以定義多個名稱相同但參數列表(參數類型、參數個數或參數順序)不同的函數。這樣,編譯器可以根據傳遞的參數自動選擇合適的函數來執行。
函數重載的要點:
- 函數名相同:重載的函數必須具有相同的函數名。
- 參數列表不同:重載的函數必須有不同的參數列表,這包括參數的類型、數量或順序。
- 返回類型不同不是重載的標準:在C++中,函數的返回類型不能用來區分重載函數。即使兩個函數有相同的名稱和參數列表,但返回類型不同,它們也不會被認為是重載函數,而是會導致編譯錯誤。
函數重寫(Overriding)
函數重寫通常發生在面向對象編程的繼承關系中。子類可以提供一個與父類方法簽名(即方法名和參數列表)完全相同的方法,從而覆蓋父類中的方法實現。當通過子類對象調用該方法時,將執行子類中的方法,而不是父類中的方法。
函數重寫的要點:
- 方法名相同:重寫的方法必須具有與父類中被重寫的方法相同的名稱。
- 參數列表相同:重寫的方法必須與父類中被重寫的方法有相同的參數列表。
- 返回類型兼容:重寫的方法的返回類型必須與父類中被重寫的方法的返回類型相同或是其子類型(協變返回類型)。
- 訪問權限不能更嚴格:重寫的方法的訪問權限不能低于父類中被重寫的方法的訪問權限。
返回值是否能區分函數重載
如前所述,在C++中,函數的返回類型不能用來區分重載函數。重載函數的區分主要基于函數名和參數列表。因此,返回值不能用于區分函數重載。
總結來說,函數重載和函數重寫的主要區別在于它們的用途和定義方式。函數重載用于在同一作用域內提供多個具有相同名稱但參數列表不同的函數,而函數重寫則用于在子類中覆蓋父類的方法實現。同時,函數的返回類型不能用于區分重載函數,但在函數重寫中,返回類型必須兼容。
- 8.算法題-合并兩個有序數組類似A{-1,5,Invalid,10,Invalid,Invalid,11}(Invalid是占位符,合并的結果放進A里面),B{2,3,5,8},要求不額外開辟空間。分析時間復雜度
加一個函數重寫和隱藏的區別:
函數重寫(Overriding)和隱藏(Hiding)在面向對象編程中都有其特定的用途和規則,但它們之間存在明顯的區別。
函數重寫主要用于類的繼承關系中。子類可以提供一個與父類方法簽名(即方法名和參數列表)完全相同的方法,從而覆蓋父類中的方法實現。當通過子類對象調用該方法時,將執行子類中的方法,而不是父類中的方法。這體現了多態性,使得子類能夠根據自身的需要定制或擴展父類的行為。
而函數隱藏,特別是當涉及到派生類和基類時,通常發生在以下情況:派生類的函數與基類的函數同名,但參數列表可能相同或不同。此時,基類的函數被隱藏,無論基類中的函數是否被
virtual
修飾。這種隱藏確保了派生類中的函數會屏蔽與其同名的基類函數,從而改變了函數調用的行為。以下是函數重寫和隱藏的主要區別:
- 目的和機制:函數重寫是為了在子類中改變或擴展父類方法的行為,而隱藏則是為了確保派生類中的函數能夠屏蔽與其同名的基類函數。
- 與多態性的關系:函數重寫是多態性的一個體現,允許子類以不同的方式實現相同的方法名。而隱藏并不直接涉及多態性,它更多地關注于函數名的屏蔽和可見性。
- 參數列表的要求:在函數重寫中,子類方法的參數列表必須與父類中被重寫的方法完全相同。而在隱藏中,派生類的函數與基類的函數可以有相同或不同的參數列表。
- 對
virtual
關鍵字的要求:在函數重寫中,被重寫的基類方法必須有virtual
修飾符,以支持動態綁定和運行時多態性。而在隱藏中,基類方法是否有virtual
修飾并不影響隱藏的發生。理解這些區別對于正確設計和使用面向對象編程中的類和繼承關系至關重要。它們有助于確保代碼的可讀性、可維護性和正確性,同時允許開發人員根據具體需求定制類的行為。
騰訊云智(3.26)-后臺開發-40min
1.自我介紹
2.項目介紹
3.項目提問
日志系統:雙緩沖區讀寫問題
云備份:斷點續傳、熱點文件管理、壓縮效率
4.說一下堆區和棧區,為什么要劃分出這兩個區
5.函數是如何調用的?
6.介紹一下指針和引用,它們在作為參數類型時,如何傳遞參數?
7.說一下常用的索引
8.MySQL引擎有哪些,說一下 InnoDB 和 MyISAM 的區別
9.說一下事務
10.說一下 MVCC 機制
11.隔離級別有哪些?MVCC 機制用于哪些隔離級別?
12.說一下 MVCC 的實現原理
13.MVCC 解決了哪些問題?
14.MVCC 機制如何解決幻讀?介紹一下MySQL中的鎖機制,說一下間隙鎖的使用及原理
15.索引如何優化?
16.說一下 select、poll、epoll
17.poll 和 epoll 的使用場景
18.輸入 URL 后發生的事情
19.HTTP 基于什么協議實現?
20.如何使用 HTTP 協議與服務器連接(TCP三次握手)
21.HTTP 和 HTTPS 的區別?
22.HTTPS 如何確保安全性?
23.為什么不能只使用非對稱加密?
24.說一下 CA 證書
25.CA證書是由誰傳輸的?
26.如何使用 CA 證書(CA 證書是如何保證安全的)?
27.如果訪問兩個不同的網站,如何獲取 CA 的公鑰?
28.手撕算法:3. 無重復字符的最長子串
- 問算法時間復雜度
騰訊QQ部門C++二面(實習)
- 什么時候開始接觸計算機的?平常是怎樣學習的?
- 了解過C++20的特性嗎?(我說我了解過C++11)
- 介紹一下智能指針是干什么用的?是怎么實現的?
- 介紹一下你的兩個項目
- 說一說這個項目為什么比malloc函數快?
- 你有沒有思考過為什么C語言中要使用malloc而不使用這個項目?這個項目不是更優嗎?
- 做這兩個項目的時候有沒有遇見什么難點?最后是怎樣解決的?
- 這兩個項目有沒有什么缺陷?使用起來有bug嗎?
- 手撕算法題:判斷鏈表中是否存在環?(杭哥上課講的原題,包會的)
- 手撕算法題:找出兩個數組中最長的相同的子數組(dp問題,看了算法課就能做)
- 手撕算法題:全排列 (算法課原題,秒了)
- 公司在深圳,你能來吧?什么時候可以到崗?實習時長多久?
- 平時有使用過GPT解決代碼中出現的問題嗎?(它們部門好像經常用)
面試官說他很討厭八股文,所以問的問題全是和項目相關的,你根本水不了
最后反問環節他回答的:公司注重語言基礎,獨立思考和找到解決問題的方法的能力
騰訊QQ部門C++ HR面(實習,30min)
- 全方位,詳細的介紹一下你自己
- 你當初為什么要做這些項目?(行為面試)
- 你在寫博客的過程中,最大的收獲是什么?
- 你來應聘工作,最看重公司的哪些方面?
- 你對我們公司了解有多少?
- 手里有其他公司的offer嗎?目前有哪些面試流程?
- 如果網易和我們都給你發了offer,你怎樣考慮?
- 你有沒有女朋友?未來實習或轉正后工作地點和女朋友商量過嗎?
- 未來對自己的職業規劃是怎樣的?
- 如果正式給你發offer,你大概多久能到崗?能實習多久?
最后反問階段,面試官透露,騰訊每年的應屆生中有80%是實習轉正(之前以為只有60%),并且今年互聯網有回暖,轉正的機會會更大
、
騰訊QQ部門C++三面
- 介紹一下你的第二個項目(此面是關于HTTP服務器項目的,放在面試筆記了)
- 除了使用線程池可以一次性處理多個網絡請求外,你還能想到什么方法?
- 你編寫服務器時為什么使用了線程池,而沒有使用更優的多路轉接epoll?
- 你測試過你的項目在同時收到幾個請求時會掛掉?那最多可以有多少線程并發訪問?
- 你怎樣保證在服務器收到客戶端的數據后。能夠盡快的處理完數據并構建響應?
- 了解過json嗎?
網易雷火 服務器開發二面 (C++實習)
- 講一下你的第一個項目是怎樣實現的?
- 這個項目你做過什么樣的優化?時間上有優化了,空間上呢?
- 在這個項目中, 為什么unordered_map的查找效率比較低下?
- 你的優化策略是使用基數樹來代替unordered_map,那么前者對比后者優在哪兒?
- 你的項目與malloc函數做過時間上的對比,但你做過空間利用率的對比嗎?
- 你的項目只測試了多線程情況下,如果是單線程,它和malloc哪個更優,你有比較過嗎?
- 了解過什么是協程嗎?
- 一共有五臺打印機(共享資源,同時只能被一個線程使用),每個線程需要申請兩臺打印機后進行打印,請問最多允許幾個線程共同進入臨界區?
- 游戲場景題: 玩家與npc對話時,若npc說的話太長了,玩家需要左右滑動才能看完npc的對話,十分不方便用戶游玩.而策劃在寫npc對話時,使用了符號"]"的地方代表這個地方可以分頁,文中出現{, . ? !}的地方也可以進行分頁.現在給你一段策劃寫好的npc對話,設超過了x個字后就需要分頁,請寫出一段偽代碼來實現: 1. 讓npc的對話的分頁盡量少 2. 不能出現讓玩家左右滑動的情況 3. 盡量讓每個分段的長度看起來一樣
二面被面試官拷打了,二面已掛
小西科技一面
1.自我介紹
2.簡歷上的專業技能是怎么學習的
3.介紹項目(只是問了幾個問題,沒有細聊)
4.數組名和指針的區別
5.結構體字節對齊
6.智能指針有哪些,區別?
7.STL中幾種map的區別
8.map和unordered_map的查找效率和空間占用,插入效率
9.瀏覽器輸入網址,在tcp/ip網絡協議層全流程大概
10.tcp三次握手對應的socket的函數,以及狀態變化
11.要發送1000字節數據,send()函數返回500代表什么含義?是什么問題導致的?之后需要做什么處理?
`send()` 函數在 Unix-like 的系統(如 Linux)中用于在網絡連接上發送數據。當 `send()` 函數被調用時,它嘗試將指定的數據發送出去,但返回的值并不一定是你試圖發送的全部數據量。
如果 `send()` 函數返回 500,這表示有 500 字節的數據被成功地發送到了網絡上,但還有 500 字節的數據沒有被發送。這通常是由以下原因導致的:
1. **TCP 的流控制**:TCP 是一個面向連接的、可靠的、字節流的協議。它使用滑動窗口機制進行流控制,以防止發送方發送過多的數據,導致接收方無法處理。如果接收方的窗口大小小于發送的數據量,那么 `send()` 可能無法一次性發送所有數據。
2. **網絡擁塞**:網絡上的擁塞也可能導致 `send()` 無法一次性發送所有數據。例如,如果中間路由器或交換機上有大量的數據包等待處理,那么新的數據包可能需要等待。
3. **緩沖區限制**:操作系統或網絡棧的發送緩沖區可能有限制,當緩沖區滿時,`send()` 將無法繼續發送數據。針對這個問題,你應該采取以下措施:
1. **非阻塞發送**:如果你的應用程序是非阻塞的,那么你可能需要檢查 `send()` 的返回值,并在需要時再次調用 `send()` 來發送剩余的數據。
2. **阻塞發送**:如果你的應用程序是阻塞的,并且你希望發送所有數據后再繼續,那么你應該在循環中調用 `send()`,直到所有數據都被發送。但請注意,這可能會導致你的應用程序在網絡擁塞或接收窗口小的時候被阻塞。
3. **錯誤處理**:確保檢查 `send()` 的返回值是否為 -1,這表示發送數據時出現了錯誤。在這種情況下,你應該使用 `errno` 來獲取更詳細的錯誤信息。最后,請注意,對于 TCP 連接,數據是按字節流發送的,而不是按消息發送的。因此,接收方可能不會一次接收到所有的數據,或者可能不會以你發送的順序接收到數據。因此,在設計和實現網絡通信程序時,需要考慮到這些因素。
12.Linux中查看進程cpu占用資源情況
13.那如果在多線程下,某個進程的占用達到200%,怎么去查看具體的原因
反問:
1.這個技術管培生具體是怎樣的
培養全面復合型技術人才,java,python,C++,go云計算,AI,后端都有涉及,工作中實際解決問題不僅僅是一種語言技術
歷史遺留的項目維護需要其他語言,新的東西和舊的東西,要求會的東西比較多
2.
秋招找工作,最主要就是基礎知識掌握,了解它的原理,有自己的見解,把書本上的知識用自己的理解表述出來,理解很重要
實習生對項目的看重不是很多(確實,基本沒問項目),更多的是基礎知識掌握清除