OC

作者:南澤1
鏈接:https://zhuanlan.zhihu.com/p/146761745
來源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

1. OC語法

1. OC中對(duì)象的結(jié)構(gòu)(騰訊一面)

  1. Instance對(duì)象

  2. 如果是NSObject對(duì)象,對(duì)象中只有一個(gè)isa指針,在64位中占16個(gè)字節(jié)(可以通過malloc_size函數(shù)獲得),但實(shí)際只用到了8個(gè)字節(jié)(可以通過class_getInstanceSize函數(shù)獲得)。

  3. 這個(gè)isa指針指向了class類對(duì)象,通過isa指針&isa_mask可以獲得NSObject類的地址。

  4. 如果自定義的類,如果增加了屬性或成員變量,對(duì)象中會(huì)有成員變量值得存儲(chǔ)地址。

  5. 對(duì)象方法、屬性、成員變量、協(xié)議信息存放在類對(duì)象中,類方法存放在元類對(duì)象(可以通過get_class獲得)中

  6. class對(duì)象

[圖片上傳失敗...(image-609f4d-1592965813716)]

  1. meta-class對(duì)象

  2. isa指針指向了基類的meta-class對(duì)象,superClass指針指向了父類的meta-class對(duì)象?;惖膍eta-class對(duì)象的superClass指針指向了基類的class對(duì)象
    2.結(jié)構(gòu)與class對(duì)象一致,只是只存儲(chǔ)了類方法信息

4 isa指針

  1. 在arm64架構(gòu)之前isa指針直接存儲(chǔ)了class、meta-class對(duì)象的地址
  2. 在arm64之后isa指針經(jīng)過優(yōu)化,使用了公用體(union)結(jié)構(gòu)

[圖片上傳失敗...(image-9414c0-1592965813716)]

2. assign、strong、weak、copy、unsafe_unretained

  1. strong:一般用于id類型和對(duì)象的修飾符,是使用__strong修飾符,instance對(duì)象會(huì)持有該對(duì)象,setter方法中會(huì)調(diào)用retain,并且retainCount+1
  2. assign:一般用于基本數(shù)據(jù)類型,是使用__unsafe_unretained修飾符,setter時(shí)會(huì)直接賦值
  3. weak:是使用__weak修飾符,如果retainCount為0,對(duì)象會(huì)被自動(dòng)釋放,并設(shè)置成nil
  4. copy:是使用__strong修飾符,但是賦值的是被賦值的對(duì)象
  5. unsafe_unretained:是使用__unsafe_unretained修飾符,

3. assing可以使用在對(duì)象中嗎(頭條一面)
可以,但會(huì)造成壞內(nèi)存訪問的錯(cuò)誤
4. weak如何實(shí)現(xiàn)自動(dòng)賦nil(頭條一面)
runtime 對(duì)注冊(cè)的類, 會(huì)進(jìn)行布局,對(duì)于 weak 對(duì)象會(huì)放入一個(gè) hash 表中。 用 weak 指向的對(duì)象內(nèi)存地址作為 key,當(dāng)此對(duì)象的引用計(jì)數(shù)為0的時(shí)候會(huì) dealloc, 在這個(gè) weak 表中搜索,找到所有以key為鍵的 weak 對(duì)象,從而設(shè)置為 nil。
5. 可變數(shù)組的實(shí)現(xiàn)原理(頭條二面)
__NSArrayM 用了環(huán)形緩沖區(qū) (circular buffer),環(huán)形緩沖區(qū)有一些非??岬膶傩?。尤其是,除非緩沖區(qū)滿了,否則在任意一端插入或刪除均不會(huì)要求移動(dòng)任何內(nèi)存。我們來分析這個(gè)類如何充分利用環(huán)形緩沖區(qū)來使得自身比 C 數(shù)組強(qiáng)大得多。在任意一端插入或者刪除,只是修改offset參數(shù),不需要移動(dòng)內(nèi)存,我們?cè)L問的時(shí)候只是不和普通的數(shù)組一樣index多少就是多少,這里會(huì)計(jì)算加上offset之后處理的值取數(shù)據(jù),而不是插入頭和尾巴的時(shí)候,環(huán)形結(jié)構(gòu)會(huì)根據(jù)最少移動(dòng)內(nèi)存指針的方式插入,例如要在A和B之間插入,按照C的數(shù)組,我們需要把B到E的元素移動(dòng)內(nèi)存,但是環(huán)形緩沖區(qū)的設(shè)計(jì),我們只要把A的值向前移動(dòng)一個(gè)單位內(nèi)存,即可,同時(shí)修改offset偏移量,就能保證最小的移動(dòng)單元來完成中間插入。
往中部插入對(duì)象有非常相似的結(jié)果。合理的解釋就是,__NSArrayM 試著去最小化內(nèi)存的移動(dòng),因此會(huì)移動(dòng)最少的一邊元素。
NSMutableArray 是一個(gè)高級(jí)抽象數(shù)組,解決了 C 風(fēng)格數(shù)組對(duì)應(yīng)的缺點(diǎn)。(C數(shù)組插入的時(shí)候都會(huì)移動(dòng)內(nèi)存,不是O(1),用到了環(huán)形緩沖區(qū)數(shù)據(jù)結(jié)構(gòu)來處理內(nèi)存移動(dòng)的損耗)
但是可變數(shù)組任意一端插入或刪除能有固定時(shí)間的性能。而且在中間插入和刪除的時(shí)候都會(huì)試著去移動(dòng)最小化內(nèi)存。
環(huán)形緩沖區(qū)的數(shù)據(jù)結(jié)構(gòu)如果是連續(xù)數(shù)組結(jié)構(gòu),在擴(kuò)容的時(shí)候難免會(huì)移動(dòng)大量內(nèi)存,因此用鏈表實(shí)現(xiàn)環(huán)形緩沖會(huì)更好
6. KVO的實(shí)現(xiàn)原理(美團(tuán)一面、阿里一面)

  1. 通過runtime API動(dòng)態(tài)生成一個(gè)子類,讓instance對(duì)象的isa指針只想這個(gè)子類,
  2. 當(dāng)修改instance對(duì)象屬性的時(shí)候,會(huì)調(diào)用Fondation框架里的NSSetXXXValueAndNotify方函數(shù)
    -willChangeValueForKey
    調(diào)用父類原有的set方法
    -didChangeValueForKey
    內(nèi)部觸發(fā)器會(huì)調(diào)用監(jiān)聽方法-observeValueForKeyPath:ofObject:change:context:

7. Block的循環(huán)引用、如何解決、原理(阿里一面)
block的本質(zhì)是封裝了函數(shù)調(diào)用和環(huán)境的代碼塊,但我感覺可以把它看成是一個(gè)對(duì)象,因?yàn)閎lock內(nèi)部也有isa指針

  1. 三種block:globalBlock、stackBlock、mallocBlock
  2. block在修飾auto變量是值傳遞,在修飾靜態(tài)變量是指針傳遞,在修飾全局變量不需要傳遞參數(shù)
  3. 如果block被拷貝到堆上,內(nèi)部會(huì)調(diào)用_block_object_assign,如果auto對(duì)象是被__strong或__copy修飾會(huì)形成強(qiáng)引用
  4. 可以用__weak或__unsafe_unretained

8. Block和delegate的比較

  1. 從源頭上理解和區(qū)別block和delegate
    delegate運(yùn)行成本低,block的運(yùn)行成本高。
    block出棧需要將使用的數(shù)據(jù)從棧內(nèi)存拷貝到堆內(nèi)存,當(dāng)然對(duì)象的話就是加計(jì)數(shù),使用完或者block置nil后才消除。delegate只是保存了一個(gè)對(duì)象指針,直接回調(diào),沒有額外消耗。就像C的函數(shù)指針,只多做了一個(gè)查表動(dòng)作。
  2. 從使用場景區(qū)別block和delegate
    有多個(gè)相關(guān)方法。假如每個(gè)方法都設(shè)置一個(gè) block, 這樣會(huì)更麻煩。而 delegate 讓多個(gè)方法分成一組,只需要設(shè)置一次,就可以多次回調(diào)。當(dāng)多于 3 個(gè)方法時(shí)就應(yīng)該優(yōu)先采用 delegate。當(dāng)1,2個(gè)回調(diào)時(shí),則使用block。
  3. delegate更安全些,比如: 避免循環(huán)引用。使用 block 時(shí)稍微不注意就形成循環(huán)引用,導(dǎo)致對(duì)象釋放不了。這種循環(huán)引用,一旦出現(xiàn)就比較難檢查出來。而 delegate 的方法是分離開的,并不會(huì)引用上下文,因此會(huì)更安全些。
  4. delegate回調(diào)返回的參數(shù)被限制在了 NS 類的范圍內(nèi),數(shù)量也很有限(當(dāng)然可以用直接調(diào)用方法的形式在繞過,并不推薦;也可以用 Array 套著傳, 不過這樣需要有文檔支持,不然不夠清晰,回調(diào)方法也需要獨(dú)立的驗(yàn)證,故也不推薦)。

如果這個(gè)回調(diào)是一個(gè)不定期觸發(fā),或者會(huì)多次觸發(fā)的,那么 Delegation 應(yīng)該更適合;如果這個(gè)回調(diào)是一個(gè)一次性的,并且和調(diào)用方法是單線性關(guān)系的,那么 Block 應(yīng)該更適合。在不同的執(zhí)行線(不是線程),不同的執(zhí)行次數(shù)、執(zhí)行數(shù)量上的區(qū)別,是鑒別使用哪一種回調(diào)的最好判斷方法。
9. 講一講響應(yīng)鏈(美團(tuán)二面)

  1. 事件的每個(gè)類型,UIKit指定一個(gè)第一響應(yīng)者,然后最先發(fā)送事件到這個(gè)對(duì)象。
  2. App中包含一個(gè)UILable,UITextField,UIButton,以及2個(gè)backgroundView,如果UITextField不能響應(yīng)事件,UIKit發(fā)送事件到UITextField的父視圖(UIView)對(duì)象,隨后是UIWindow的根視圖(UIView)。從根視圖,響應(yīng)者鏈在事件傳遞到UIWindow之前,先轉(zhuǎn)移到所擁有的UIViewController。如果UIWindow不能處理事件,UIKit傳遞事件到UIApplication對(duì)象,也可能到app delegate如果對(duì)象是UIResponder的實(shí)例并且不是響應(yīng)鏈的一部分。

[圖片上傳失敗...(image-69c704-1592965813715)]

10. 如何通過一個(gè)view查找它所在的viewController(美團(tuán)二面)

UIResponser *responser = self.nextResponser;
do  {
    if ([responser isKindOfClass:[UIVC class]])
        return (UIVC *)responser;
    responser = response.nextResponser;
} while (responser);

11. 持久化(阿里一面)

  1. NSUserDefaults:用于存放小數(shù)據(jù),只能存儲(chǔ)系統(tǒng)自帶的數(shù)據(jù)類型,自定義的對(duì)象無法存儲(chǔ)

  2. 不需要關(guān)心文件名(不需要設(shè)置路徑)

  3. 鍵值對(duì)存儲(chǔ)(賬號(hào)相關(guān)信息) 對(duì)象存儲(chǔ)

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    //放到緩存里,并不會(huì)馬上放到文件里面
[userDefaults setObject:@"123" forKey:@"account"]; //對(duì)象
[userDefaults setObject:@"123456" forKey:@"pwd"];
//BOOL類型
[userDefaults setBool:YES forKey:@"status"];
//在ios7 默認(rèn)不會(huì)馬上跟硬盤同步  同步操作 起到立即存儲(chǔ)的作用
[userDefaults synchronize];

  1. 3屬性列表property list:只能存儲(chǔ)系統(tǒng)自帶的數(shù)據(jù)類型,一般實(shí)際開發(fā)中存儲(chǔ)字典、數(shù)組,自定義的模型無法進(jìn)行存儲(chǔ)
 NSString *kUserPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"latestQuery.plist"];
NSArray  *array = @[];
[arr writeToFile:kUserPath atomically:YES];

4.歸檔NSKeyedArchiver:可以存儲(chǔ)自定義對(duì)象,自定義對(duì)象想要?dú)w檔,則自定義對(duì)象必須遵守NSCoding協(xié)議,實(shí)現(xiàn)協(xié)議方法

//歸檔
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
//編碼
[archiver encodeObject:self.afterSelectedArray forKey:GMEncodeKey];
//結(jié)束編碼
[archiver finishEncoding];

//解檔
NSData *undata = [[NSData alloc] initWithContentsOfFile:toFileName];
//解檔輔助類
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:undata];
//解碼并解檔出model
NSArray *tempArray = [unarchiver decodeObjectForKey:GMEncodeKey];
//關(guān)閉解檔
[unarchiver finishDecoding];

  1. 數(shù)據(jù)庫:用于存放一條條的數(shù)據(jù)
  2. 文件:用于存放圖片、文件、音視頻等數(shù)據(jù)

12. 多態(tài)(騰訊一面) iOS的多態(tài)基于了runtime,可以動(dòng)態(tài)綁定數(shù)據(jù)類型,添加方法,屬性等

13. layoutIfNeeded和setNeedsLayout的區(qū)別(頭條二面)
更新布局會(huì)調(diào)用layoutIfNeeded

  • setNeedsLayout
    會(huì)標(biāo)記為需要重新布局,異步調(diào)用layoutIfNeeded刷新布局,但不是立刻執(zhí)行,是在RunLoop下一輪循環(huán)結(jié)束前刷新。對(duì)于這一輪runloop之內(nèi)的所有布局和UI上的更新只會(huì)刷新一次,layoutSubviews一定會(huì)被調(diào)用。
  • layoutIfNeeded
    如果有需要刷新標(biāo)記,會(huì)立刻調(diào)用layoutSubviews進(jìn)行刷新操作,如果沒有則不調(diào)用

14. isEquel和hash的關(guān)系(頭條二面)
兩個(gè)對(duì)象isEquel相等,hash一定相等,但hash相等,isEque不一定相等
15. 有哪些編碼方式(頭條一面)

NSASCIIStringEncoding = 1,      /* 0..127 only */
NSNEXTSTEPStringEncoding = 2,
NSJapaneseEUCStringEncoding = 3,
NSUTF8StringEncoding = 4,
NSSymbolStringEncoding = 6,

2. Runtime
1. 消息調(diào)用的過程(美團(tuán)一面、阿里一面)

  1. 首先會(huì)在reveiceClasscache中查找方法
  2. 如果沒有找到,會(huì)到reveiceClassclass_rw_t的方法列表中查找
  3. 如果找不到,會(huì)到superClasscache中查找
  4. 如果找不到,會(huì)到superClassclass_rw_t的方法列表中查找
  5. 如果找不到,會(huì)遞歸3操作,直到superClassnil
  6. 如果superClassnil,會(huì)進(jìn)入消息動(dòng)態(tài)解析
  7. 如果有動(dòng)態(tài)解析,進(jìn)入消息轉(zhuǎn)發(fā)
  8. 如果沒有動(dòng)態(tài)解析,會(huì)調(diào)用+resolveInstanceMethod:+resolveClassMethod:
  9. 動(dòng)態(tài)解析過后,會(huì)重新走消息發(fā)送機(jī)制
  10. 如果沒有動(dòng)態(tài)解析,會(huì)調(diào)用forwardingTargetForSeletor
  11. 如果返回不為nil,調(diào)用objc_msgSend(返回值,SEL)
  12. 如果返回nil,會(huì)調(diào)用methodSignatureForSeletor
  13. 如果返回值不為nil,調(diào)用forwardingInvocation
  14. 返回為nil,報(bào)錯(cuò)doesNotRecognizeSelector

2. 如何hook一個(gè)對(duì)象的方法,而不影響其它對(duì)象(頭條二面)

  1. 可以在分類的load方法里,或是initialaze里使用dispatch_once,
  2. 調(diào)用class_addMethod判斷是否可以添加方法,可以的話調(diào)用class_replaceMethod函數(shù)
  3. 或者調(diào)用method_exchangeImplementations函數(shù)

3. runtime如何通過selector找到對(duì)應(yīng)的IMP地址(阿里一面)

  1. IMP class_getMethodImplementation(Class cls, SEL name); 參考2.1 消息調(diào)用的過程
  2. IMP method_getImplementation(Method m) 直接取method_t中的imp指針

3. RunLoop
1. runloop內(nèi)部實(shí)現(xiàn)邏輯?(阿里一面)

  1. source0:觸摸事件處理、performSelector:onThread
  2. source1:基于port之間的線程通信、系統(tǒng)時(shí)間捕捉
  3. Timers:NSTimer、performSelector:withObject:afterDelay:
  4. Observers:用于監(jiān)聽RunLoop的狀態(tài)、刷新UI(BeforeWaiting)、AutoreleasePool(BeforeWaiting)

[圖片上傳失敗...(image-92e0a3-1592965813715)]

4. 多線程
1. 隊(duì)列、進(jìn)程和線程的區(qū)別(阿里一面、頭條一面、百度一面)

  1. 進(jìn)程:進(jìn)程是操作系統(tǒng)資源分配的基本單位。
  2. 線程:線程是任務(wù)調(diào)度和執(zhí)行的基本單位。一個(gè)進(jìn)程可以由很多個(gè)線程組成,線程間共享進(jìn)程的所有資源,每個(gè)線程有自己的堆棧和局部變量。線程由CPU獨(dú)立調(diào)度執(zhí)行,在多CPU環(huán)境下就允許多個(gè)線程同時(shí)運(yùn)行。同樣多線程也可以實(shí)現(xiàn)并發(fā)操作,每個(gè)請(qǐng)求分配一個(gè)線程來處理。

地址空間:同一進(jìn)程的線程共享本進(jìn)程的地址空間,而進(jìn)程之間則是獨(dú)立的地址空間。
資源擁有:同一進(jìn)程內(nèi)的線程共享本進(jìn)程的資源如內(nèi)存、I/O、cpu等,但是進(jìn)程之間的資源是獨(dú)立的。

  1. 隊(duì)列:隊(duì)列是一種特殊的線性表

2. 進(jìn)程間通信的方式(百度一面)

  1. 管道pipe:管道是一種半雙工的通信方式,數(shù)據(jù)只能單向流動(dòng),而且只能在具有親緣關(guān)系的進(jìn)程間使用。進(jìn)程的親緣關(guān)系通常是指父子進(jìn)程關(guān)系。
  2. 命名管道FIFO:有名管道也是半雙工的通信方式,但是它允許無親緣關(guān)系進(jìn)程間的通信。
  3. 消息隊(duì)列MessageQueue:消息隊(duì)列是由消息的鏈表,存放在內(nèi)核中并由消息隊(duì)列標(biāo)識(shí)符標(biāo)識(shí)。消息隊(duì)列克服了信號(hào)傳遞信息少、管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點(diǎn)。
  4. 共享存儲(chǔ)SharedMemory:共享內(nèi)存就是映射一段能被其他進(jìn)程所訪問的內(nèi)存,這段共享內(nèi)存由一個(gè)進(jìn)程創(chuàng)建,但多個(gè)進(jìn)程都可以訪問。共享內(nèi)存是最快的 IPC 方式,它是針對(duì)其他進(jìn)程間通信方式運(yùn)行效率低而專門設(shè)計(jì)的。它往往與其他通信機(jī)制,如信號(hào)兩,配合使用,來實(shí)現(xiàn)進(jìn)程間的同步和通信。
  5. 信號(hào)量Semaphore:信號(hào)量是一個(gè)計(jì)數(shù)器,可以用來控制多個(gè)進(jìn)程對(duì)共享資源的訪問。它常作為一種鎖機(jī)制,防止某進(jìn)程正在訪問共享資源時(shí),其他進(jìn)程也訪問該資源。因此,主要作為進(jìn)程間以及同一進(jìn)程內(nèi)不同線程之間的同步手段。
  6. 套接字Socket:套解口也是一種進(jìn)程間通信機(jī)制,與其他通信機(jī)制不同的是,它可用于不同及其間的進(jìn)程通信。
  7. 信號(hào) ( sinal ) : 信號(hào)是一種比較復(fù)雜的通信方式,用于通知接收進(jìn)程某個(gè)事件已經(jīng)發(fā)生。

3. 一個(gè)進(jìn)程有哪些區(qū)(百度一面)
參考5.1
4. 多線程的方式和它們的區(qū)別(頭條一面、阿里一面)

[圖片上傳失敗...(image-8a9f22-1592965813715)]

5. 線程死鎖的四個(gè)條件(阿里一面)

  1. 互斥條件:進(jìn)程對(duì)所分配到的資源不允許其他進(jìn)程進(jìn)行訪問,若其他進(jìn)程訪問該資源,只能等待,直至占有該資源的進(jìn)程使用完成后釋放該資源
  2. 請(qǐng)求和保持條件:進(jìn)程獲得一定的資源之后,又對(duì)其他資源發(fā)出請(qǐng)求,但是該資源可能被其他進(jìn)程占有,此事請(qǐng)求阻塞,但又對(duì)自己獲得的資源保持不放
  3. 不可剝奪條件:是指進(jìn)程已獲得的資源,在未完成使用之前,不可被剝奪,只能在使用完后自己釋放
  4. 環(huán)路等待條件:是指進(jìn)程發(fā)生死鎖后,必然存在一個(gè)進(jìn)程--資源之間的環(huán)形鏈

6. 線程安全的題(頭條一面)

  1. 資源共享:一塊資源可能被多個(gè)線程共享,比如多個(gè)線程同時(shí)訪問同一個(gè)對(duì)象、同一個(gè)變量、同一個(gè)文件
  2. 當(dāng)多個(gè)線程同時(shí)訪問一塊資源時(shí),可能發(fā)生數(shù)據(jù)錯(cuò)亂或線程安全問題

7. iOS中有哪些鎖(頭條一面、騰訊一面)

  1. OSSpinLock
  2. os_unfiar_lock
  3. ptheard_metux_lock
  4. dispatch_semaphore
  5. NSLock
  6. NSRecursiveLock
  7. NSCondition
  8. NSConditionLock

8. 自旋鎖和互斥鎖的區(qū)別(頭條二面)
1. 自旋鎖適用于: 1. 預(yù)計(jì)線程等待鎖的時(shí)間很短 2. 臨界區(qū)經(jīng)常被調(diào)用,但競爭較少 3. 多核處理 4. CPU不緊張 2. 互斥鎖適用于: 1. 預(yù)計(jì)線程等待鎖的時(shí)間較長 2. 單核處理器 3. 臨界區(qū)有IO操作 4. 臨界區(qū)代碼復(fù)雜或循環(huán)量大 5. 臨界區(qū)競爭激烈
9. 線程同步的方式(騰訊一面)

  1. 可以利用加鎖的方式來保證線程同步
  2. 可以利用dispat_queue串行隊(duì)列
  3. 可以用dispatch_semaphore信號(hào)量
  4. atomic,對(duì)象的原子性,默認(rèn)在setter方法內(nèi)部加鎖
  5. 針對(duì)讀寫操作可以使用多讀單寫的操作來保證線程同步,例如dispatch_barrier_async和ptheard_rolock

10. GCD執(zhí)行原理?(阿里一面)
11. 事務(wù)的特征(阿里一面)
事務(wù)是并發(fā)控制的基本單位。所謂的事務(wù),它是一個(gè)操作序列,這些操作要么都執(zhí)行,要么都不執(zhí)行,它是一個(gè)不可分割的工作單位。例如,銀行轉(zhuǎn)賬工作:從一個(gè)賬號(hào)扣款并使另一個(gè)賬號(hào)增款,這兩個(gè)操作要么都執(zhí)行,要么都不執(zhí)行。所以,應(yīng)該把它們看成一個(gè)事務(wù)。事務(wù)是數(shù)據(jù)庫維護(hù)數(shù)據(jù)一致性的單位,在每個(gè)事務(wù)結(jié)束時(shí),都能保持?jǐn)?shù)據(jù)一致性。 針對(duì)上面的描述可以看出,事務(wù)的提出主要是為了解決并發(fā)情況下保持?jǐn)?shù)據(jù)一致性的問題。

事務(wù)具有以下4個(gè)基本特征。

  1. Atomic(原子性):事務(wù)中包含的操作被看做一個(gè)邏輯單元,這個(gè)邏單元中的操作要么全部成功,要么全部失敗。
  2. Consistency(一致性):只有合法的數(shù)據(jù)可以被寫入數(shù)據(jù)庫,否則事務(wù)應(yīng)該將其回滾到最初狀態(tài)。
  3. Isolation(隔離性):事務(wù)允許多個(gè)用戶對(duì)同一個(gè)數(shù)據(jù)進(jìn)行并發(fā)訪問,而不破壞數(shù)據(jù)的正確性和完整性。同時(shí),并行事務(wù)的修改必須與其他并行事務(wù)的修改相互獨(dú)立。
  4. Durability(持久性):事務(wù)結(jié)束后,事務(wù)處理的結(jié)果必須能夠得到固化。

5. 內(nèi)存管理
1. 介紹下內(nèi)存的幾大區(qū)域?(阿里一面)

  1. 代碼段:用于存放編譯之后的代碼
  2. 數(shù)據(jù)段:
  3. 堆段:通過malloc、calloc、alloc動(dòng)態(tài)分配的空間,分配的內(nèi)存地址越來越大,需要程序員手動(dòng)管理內(nèi)存
  4. 棧段:用于函數(shù)調(diào)用開銷,例如局部變量,分配的內(nèi)存空間地址越來越小,系統(tǒng)自動(dòng)分配內(nèi)存
  5. 內(nèi)核區(qū):

2. 淺拷貝和深拷貝的區(qū)別(阿里一面、頭條三面)
淺拷貝拷貝地址,深拷貝拷貝內(nèi)存
一般不可變量調(diào)用copy,為淺拷貝;
可變變量調(diào)用copy,或調(diào)用MutableCopy為深拷貝
3. 數(shù)組copy后里面的元素會(huì)復(fù)制一份新的嗎(頭條三面)
不會(huì)
4. 對(duì)于字符串使用strong會(huì)有什么問題?對(duì)于可變數(shù)組使用copy這樣會(huì)有什么問題?

  1. 如果賦值的是不可變字符串,沒有問題,如果賦值的和被賦值是可變字符串,則如果修改賦值對(duì)象,用strong修飾的被賦值對(duì)象也會(huì)被修改
  2. 會(huì)新創(chuàng)建一個(gè)新的不可變數(shù)組,在調(diào)用添加刪除會(huì)報(bào)錯(cuò)

5. Autorelease pool的實(shí)現(xiàn)原理(阿里一面)

  1. 內(nèi)部結(jié)構(gòu)主要有__atAutoreleasePool、autoreleasePoolPage
  2. 調(diào)用了autorelease的對(duì)象都由autoreleasePoolPage來管理,
  3. 調(diào)用了push操作后會(huì)有一個(gè)POOL_BOUNDARY入棧,
  4. 然后調(diào)用了autorelease的對(duì)象都會(huì)加到autoreleasePoolPage,
  5. 如果autoreleasePoolPage內(nèi)存不夠他會(huì)創(chuàng)建一個(gè)新的autoreleasePoolPage,原先的child指向新的autoreleasePoolPage,新的perent指向原先的,
  6. 在調(diào)用pop以后,會(huì)從最后一個(gè)入棧的對(duì)象開始往前release,知道遇到POOL_BOUNDARY為止

6. 性能優(yōu)化
1. 性能優(yōu)化(阿里二面)

  1. CPU

  2. 盡量使用輕量級(jí)對(duì)象,比如用不到事件處理的地方,可以考慮使用CALayer取代UIView

  3. 不要頻繁調(diào)用UIView的相關(guān)屬性,比如frame、bounds、transform等屬性,盡量減少不必要的修改

  4. 盡量提前計(jì)算好布局,在有需要時(shí)一次調(diào)整,不要多次修改屬性

  5. autolayout比直接設(shè)置frame小號(hào)更多CPU資源

  6. 圖片的size最好剛好跟UIImageView的size一樣

  7. 控制一下線程最大并發(fā)數(shù)

  8. 盡量把耗時(shí)操作放到子線程

  9. 文本處理(尺寸計(jì)算、繪制)

  10. 圖片處理(解碼、繪制)

  11. GPU

  12. 盡量減少短時(shí)間內(nèi)的圖片大量顯示,盡可能的合成一張圖片顯示

  13. GPU最大能處理的紋理是4096 x 4096,一但超過這個(gè)尺寸,就需要占用CPU資源處理,所以紋理最好不要超過這個(gè)尺寸

  14. 盡量減少視圖的數(shù)量和層次

  15. 盡量不要使用透明度

  16. 盡量不要出現(xiàn)離屏渲染(在當(dāng)前屏幕緩沖區(qū)以外,開出一片新的緩沖區(qū)進(jìn)行渲染操作)

  17. 需要?jiǎng)?chuàng)建新的緩沖區(qū)

  18. 離屏渲染需要多次切換上下文,先從當(dāng)前屏幕,切換到離屏屏幕,等到離屏渲染完成之后,有需要將緩沖區(qū)渲染到當(dāng)前屏幕,有需要將上下文環(huán)境從離屏屏幕切換到當(dāng)前屏幕

  19. 那些操作會(huì)造成離屏渲染

  20. 光柵化,layer.shouldRasterize = YES;

  21. 遮罩,layer.mask

  22. 圓角,同時(shí)設(shè)置layer.masksToBounds = YES 和 layer.corner > 0,可以考慮通過CoreGraphics繪制剪裁圓角,或直接使用圓角圖片

  23. 陰影,layer.shadowXXX,如果設(shè)置了layer.shadowPath就不會(huì)產(chǎn)生離屏渲染

2. 你是如何組件化解耦的?(阿里一面)
項(xiàng)目前期一般不需要組件化解耦,而且前期開發(fā)人員少,業(yè)務(wù)發(fā)展的不是特別快,不使用組件化可以保證開發(fā)進(jìn)度。但如果項(xiàng)目發(fā)展起來會(huì)出現(xiàn)很多弊端,如耦合度比較嚴(yán)重、容易出現(xiàn)沖突、業(yè)務(wù)方的開發(fā)效率不夠高(因?yàn)樗魂P(guān)心自己的組件,卻需要編譯整個(gè)項(xiàng)目)

  1. 優(yōu)點(diǎn):

  2. 加快編譯速度

  3. 提高開發(fā)效率

  4. 自由選擇開發(fā)設(shè)計(jì)模式

  5. 方便OA有針對(duì)性測試

  6. 缺點(diǎn):

  7. 資源的重復(fù)性:以前放在一起,知道哪些資源是公共資源,而組件化之后,因?yàn)楦鱾€(gè)組件都相對(duì)獨(dú)立了,所以一些資源需要重復(fù)加載,導(dǎo)致包變大了

  8. 頁面樣式:因?yàn)楠?dú)立開來,可能導(dǎo)致頁面樣式有差異??梢允褂霉步M件化解決。

3. 優(yōu)化你是從哪幾方面著手?(阿里一面)

  1. 耗電優(yōu)化

  2. CPU處理:盡可能的降低CPU和GPU的功耗

  3. 少用NSTimer

  4. 優(yōu)化IO操作

  5. 盡量不要頻繁的寫入小數(shù)據(jù),最好批量一次性寫入

  6. 讀寫大量數(shù)據(jù)時(shí),考慮用dispatch_io,其提供了基于GCD的異步操作IO文件的API。用dispatch_io系統(tǒng)會(huì)優(yōu)化磁盤訪問

  7. 數(shù)據(jù)量比較大的,建議使用數(shù)據(jù)庫(SQLite、CoreData)

  8. 網(wǎng)絡(luò):

  9. 減少、壓縮網(wǎng)絡(luò)數(shù)據(jù)

  10. 如果多次請(qǐng)求數(shù)據(jù)相同,盡量使用緩存

  11. 如果大文件下載,使用斷點(diǎn)續(xù)傳

  12. 網(wǎng)絡(luò)不可用時(shí),不要嘗試執(zhí)行網(wǎng)絡(luò)請(qǐng)求

  13. 讓用戶可以手動(dòng)取消長時(shí)間運(yùn)行、速度很慢的網(wǎng)絡(luò)請(qǐng)求,設(shè)置合適的超時(shí)時(shí)間

  14. 批量傳輸,比如下載視頻流時(shí),不要傳輸很小的數(shù)據(jù)包,直接下載整個(gè)文件或一大塊一大塊的下載。如果下載廣告,一次性下載多一些,然后慢慢展示,如果下載電子郵件,一次下載多封,不要一封一封下載

  15. 定位:

  16. 如果需要快速定位使用CLLocationManagerrequestLocation方法,定位完成后,會(huì)自動(dòng)讓定位硬件斷電。

  17. 如果不是導(dǎo)航應(yīng)用,不要實(shí)時(shí)刷新位置,定位完畢就關(guān)掉定位服務(wù)

  18. 盡量降低定位精度,比如盡量不要使用精度最高的kCLLocationAccuracyBest

  19. 需要后臺(tái)定位時(shí),盡量設(shè)置pauseLocationUpdatesAutomatically = YES,如果用戶不大可能移動(dòng)的時(shí)候會(huì)自動(dòng)暫停位置更新

  20. 盡量不要使用startMonitoringSignificantLocationChanges,優(yōu)先考慮startMonitoringForRegion

  21. 硬件檢測優(yōu)化:用戶移動(dòng)、搖晃、傾斜設(shè)備時(shí),可能觸發(fā)動(dòng)作事件,這些事件由加速器、陀螺儀、磁力計(jì)等硬件檢測,在不使用的時(shí)候,應(yīng)關(guān)閉這些設(shè)備

  22. 啟動(dòng)優(yōu)化:主要優(yōu)化冷啟動(dòng)

  23. dyld

  24. 減少動(dòng)態(tài)庫,合并一些動(dòng)態(tài)庫,清理一些不用的動(dòng)態(tài)庫

  25. 減少Objc類、分類、Seletor的數(shù)量,清理一些不用的類、分類

  26. 減少c++虛函數(shù)數(shù)量

  27. Swift盡量使用struct

  28. runtime
    initialize+dispatch_once取代load、c++靜態(tài)構(gòu)造器等

  29. main
    在不影響用戶體驗(yàn)的前提下,盡量延遲加載,盡量不放到finishLaunching方法中

  30. 安裝包優(yōu)化

  31. 資源(圖片、音視頻等)

  32. 采用無損壓縮

  33. 刪除沒有用到的資源

  34. 編輯器

  35. Strip Linked Product、Make Strings Read-Only、Symbols Hidden by Default設(shè)置為YES

  36. 去掉異常支持,Enable C++ Exceptions、Enable Objective-C Exceptions設(shè)置為NO, Other C Flags添加-fno-exceptions

  37. 利用APPCode檢測未使用的代碼

  38. 利用LLVM插件檢測出重復(fù)代碼、為被調(diào)用代碼

  39. 卡頓優(yōu)化:參考6.1

7. 第三方庫
1. Masonry的約束應(yīng)該寫在哪里(阿里一面)

  1. 在addSubView之后添加約束
  2. 相關(guān)約束對(duì)象添加之后添加約束

2. YYModel和AF源碼(阿里二面)
3. Pod update和pod install的區(qū)別(頭條二面)
在pod多少版本之前,pod update只是更新需要更新的代碼,而Pod install是更新全部代碼
不想升級(jí)specs庫,可以增加忽略參數(shù)--no-repo-update
4. SD的源碼(頭條二面)
5. 看過哪些源碼,講講思路(騰訊一面)
6. YYAsyncLayer如何異步繪制?(阿里一面)
8. 設(shè)計(jì)模式及架構(gòu)
1. MVC的一些缺點(diǎn)(頭條一面)
2. 介紹一下MVVM(阿里三面)
3. MVC和MVVM的區(qū)別(騰訊一面)
4. 架構(gòu)(阿里二面)
5. 如何自己設(shè)計(jì)json轉(zhuǎn)model(阿里二面)
6. 知道哪些設(shè)計(jì)模式(阿里三面、騰訊一面)
7. 存一個(gè)通訊錄,包括增刪改查,用什么數(shù)據(jù)結(jié)構(gòu)(騰訊一面)
8. 講一下我最滿意的一個(gè)項(xiàng)目(百度二面)
9. 介紹項(xiàng)目,主要介紹自己強(qiáng)項(xiàng)一點(diǎn)的地方(阿里二面、頭條三面)
10. 自我介紹 介紹一些項(xiàng)目難點(diǎn)(阿里三面)
11. 怎么防止別人反編譯你的app?(阿里一面)
9. 網(wǎng)絡(luò)
1. 七層模型(美團(tuán)一面、百度一面)
應(yīng)用層、表示層、會(huì)話層、網(wǎng)絡(luò)層、傳輸層、數(shù)據(jù)鏈路層、物理層
應(yīng)用層 網(wǎng)絡(luò)服務(wù)與最終用戶的一個(gè)接口。 協(xié)議有:HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP 表示層 數(shù)據(jù)的表示、安全、壓縮。(在五層模型里面已經(jīng)合并到了應(yīng)用層) 格式有,JPEG、ASCll、EBCDIC、加密格式等 會(huì)話層 建立、管理、終止會(huì)話。(在五層模型里面已經(jīng)合并到了應(yīng)用層) 對(duì)應(yīng)主機(jī)進(jìn)程,指本地主機(jī)與遠(yuǎn)程主機(jī)正在進(jìn)行的會(huì)話 傳輸層 定義傳輸數(shù)據(jù)的協(xié)議端口號(hào),以及流控和差錯(cuò)校驗(yàn)。 協(xié)議有:TCP UDP,數(shù)據(jù)包一旦離開網(wǎng)卡即進(jìn)入網(wǎng)絡(luò)傳輸層 網(wǎng)絡(luò)層 進(jìn)行邏輯地址尋址,實(shí)現(xiàn)不同網(wǎng)絡(luò)之間的路徑選擇。 協(xié)議有:ICMP IGMP IP(IPV4 IPV6) 數(shù)據(jù)鏈路層 建立邏輯連接、進(jìn)行硬件地址尋址、差錯(cuò)校驗(yàn)等功能。(由底層網(wǎng)絡(luò)定義協(xié)議) 將比特組合成字節(jié)進(jìn)而組合成幀,用MAC地址訪問介質(zhì),錯(cuò)誤發(fā)現(xiàn)但不能糾正。 物理層 建立、維護(hù)、斷開物理連接。(由底層網(wǎng)絡(luò)定義協(xié)議) TCP/IP 層級(jí)模型結(jié)構(gòu),應(yīng)用層之間的協(xié)議通過逐級(jí)調(diào)用傳輸層(Transport layer)、網(wǎng)絡(luò)層(Network Layer)和物理數(shù)據(jù)鏈路層(Physical Data Link)而可以實(shí)現(xiàn)應(yīng)用層的應(yīng)用程序通信互聯(lián)。 應(yīng)用層需要關(guān)心應(yīng)用程序的邏輯細(xì)節(jié),而不是數(shù)據(jù)在網(wǎng)絡(luò)中的傳輸活動(dòng)。應(yīng)用層其下三層則處理真正的通信細(xì)節(jié)。在 Internet 整個(gè)發(fā)展過程中的所有思想和著重點(diǎn)都以一種稱為 RFC(Request For Comments)的文檔格式存在。針對(duì)每一種特定的 TCP/IP 應(yīng)用,有相應(yīng)的 RFC文檔。
2.傳輸層和網(wǎng)絡(luò)層分別是做什么的(百度一面)
3. http有哪些部分(美團(tuán)一面、騰訊一面、頭條一面)
http協(xié)議報(bào)文 1.請(qǐng)求報(bào)文(請(qǐng)求行/請(qǐng)求頭/請(qǐng)求數(shù)據(jù)/空行) 請(qǐng)求行 求方法字段、URL字段和HTTP協(xié)議版本 例如:GET /index.html HTTP/1.1 get方法將數(shù)據(jù)拼接在url后面,傳遞參數(shù)受限 請(qǐng)求方法: GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT 請(qǐng)求頭(key value形式) User-Agent:產(chǎn)生請(qǐng)求的瀏覽器類型。 Accept:客戶端可識(shí)別的內(nèi)容類型列表。 Host:主機(jī)地址 請(qǐng)求數(shù)據(jù) post方法中,會(huì)把數(shù)據(jù)以key value形式發(fā)送請(qǐng)求 發(fā)送回車符和換行符,通知服務(wù)器以下不再有請(qǐng)求頭 2.響應(yīng)報(bào)文(狀態(tài)行、消息報(bào)頭、響應(yīng)正文) 狀態(tài)行 消息報(bào)頭 響應(yīng)正文
4. Http2.0如1.x的區(qū)別(百度一面)
5.發(fā)送一個(gè)HTTP請(qǐng)求的過程(百度二面)
6. tcp和udp的區(qū)別(美團(tuán)一面、百度一面)

  1. TCP:是面向鏈接的協(xié)議,經(jīng)過三次握手建立鏈接,鏈接成功傳輸協(xié)議、四次放手,
  2. UDP:是非鏈接協(xié)議,所以TCP比UDP安全,但因?yàn)樾枰㈡溄?,所以傳輸速度?/li>

7. get和post的區(qū)別(美團(tuán)一面)

  1. get一般用于從服務(wù)器上獲取數(shù)據(jù),post一般用于向服務(wù)器傳輸數(shù)據(jù)
  2. get采用的地址傳參,post采用報(bào)文傳參
  3. get傳輸?shù)臄?shù)據(jù)量小,一般2K,post可傳輸?shù)臄?shù)據(jù)量很大,一般默認(rèn)無限傳輸,但實(shí)際有上限(4G)
  4. get安全性非常低,post安全性較高
  5. get不能上傳文件,post可以上傳文件

8. TCP頭部多長,IP呢(騰訊一面)
IP頭部范圍為20B(不含options)~60B
UDP頭部長度是固定的,為12B(假頭部)+8B(真頭部) = 20B
TCP跟IP頭長度一樣,20B~60B,取決于有沒有options.
9. UDP可以實(shí)現(xiàn)一對(duì)多??(百度一面)
10. TCP是如何保證可靠的(百度二面)
1、確認(rèn)和重傳:接收方收到報(bào)文就會(huì)確認(rèn),發(fā)送方發(fā)送一段時(shí)間后沒有收到確認(rèn)就重傳。
2、數(shù)據(jù)校驗(yàn)
3、數(shù)據(jù)合理分片和排序:
  UDP:IP數(shù)據(jù)報(bào)大于1500字節(jié),大于MTU.這個(gè)時(shí)候發(fā)送方IP層就需要分片(fragmentation).把數(shù)據(jù)報(bào)分成若干片,使每一片都小于MTU.而接收方IP層則需要進(jìn)行數(shù)據(jù)報(bào)的重組.這樣就會(huì)多做許多事情,而更嚴(yán)重的是,由于UDP的特性,當(dāng)某一片數(shù)據(jù)傳送中丟失時(shí),接收方便無法重組數(shù)據(jù)報(bào).將導(dǎo)致丟棄整個(gè)UDP數(shù)據(jù)報(bào).
  tcp會(huì)按MTU合理分片,接收方會(huì)緩存未按序到達(dá)的數(shù)據(jù),重新排序后再交給應(yīng)用層。
4、流量控制:當(dāng)接收方來不及處理發(fā)送方的數(shù)據(jù),能提示發(fā)送方降低發(fā)送的速率,防止包丟失。
5、擁塞控制:當(dāng)網(wǎng)絡(luò)擁塞時(shí),減少數(shù)據(jù)的發(fā)送。
11. TCP為什么是三次握手和四次揮手(頭條三面)
12. 知道MTU嗎(騰訊一面)
最大輸出單元,如果在IP層要傳輸一個(gè)數(shù)據(jù)報(bào)比鏈路層的MTU還大,那么IP層就會(huì)對(duì)這個(gè)數(shù)據(jù)報(bào)進(jìn)行分片。一個(gè)數(shù)據(jù)報(bào)會(huì)被分為若干片,每個(gè)分片的大小都小于或者等于鏈路層的MTU值。當(dāng)同一網(wǎng)絡(luò)上的主機(jī)互相進(jìn)行通信時(shí),該網(wǎng)絡(luò)的MTU對(duì)通信雙方非常重要。
13. HTTPS通信的步驟
① 客戶端發(fā)送報(bào)文進(jìn)行SSL通信。報(bào)文中包含客戶端支持的SSL的指定版本、加密組件列表(加密算法及密鑰長度等)。
② 服務(wù)器應(yīng)答,并在應(yīng)答報(bào)文中包含SSL版本以及加密組件。服務(wù)器的加密組件內(nèi)容是從接受到的客戶端加密組件內(nèi)篩選出來的。
③ 服務(wù)器發(fā)送報(bào)文,報(bào)文中包含公開密鑰證書。
④ 服務(wù)器發(fā)送報(bào)文通知客戶端,最初階段SSL握手協(xié)商部分結(jié)束。
⑤ SSL第一次握手結(jié)束之后,客戶端發(fā)送一個(gè)報(bào)文作為回應(yīng)。報(bào)文中包含通信加密中使用的一種被稱Pre-master secret的隨機(jī)密碼串。該密碼串已經(jīng)使用服務(wù)器的公鑰加密。
⑥ 客戶端發(fā)送報(bào)文,并提示服務(wù)器,此后的報(bào)文通信會(huì)采用Pre-master secret密鑰加密。
⑦ 客戶端發(fā)送Finished報(bào)文。該報(bào)文包含連接至今全部報(bào)文的整體校驗(yàn)值。這次握手協(xié)商是否能夠完成成功,要以服務(wù)器是否能夠正確解密該報(bào)文作為判定標(biāo)準(zhǔn)。
⑧ 服務(wù)器同樣發(fā)送Change Cipher Spec報(bào)文。
⑨ 服務(wù)器同樣發(fā)送Finished報(bào)文。
⑩ 服務(wù)器和客戶端的Finished報(bào)文交換完畢之后,SSL連接就算建立完成。
? 應(yīng)用層協(xié)議通信,即發(fā)送HTTP響應(yīng)。
? 最后由客戶端斷開鏈接。斷開鏈接時(shí),發(fā)送close_nofify報(bào)文
14. HTTP和HTTPS區(qū)別?
① https協(xié)議需要到ca申請(qǐng)證書,一般免費(fèi)證書較少,因而需要一定費(fèi)用;http一般是免費(fèi)的。
② http是超文本傳輸協(xié)議,信息是明文傳輸;https則是具有安全性的ssl加密傳輸協(xié)議。
③ http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
④ http的連接很簡單,是無狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全。
TTP協(xié)議傳輸?shù)臄?shù)據(jù)都是未加密的,也就是明文的,因此使用HTTP協(xié)議傳輸隱私信息非常不安全,為了保證這些隱私數(shù)據(jù)能加密傳輸,于是網(wǎng)景公司設(shè)計(jì)了SSL(Secure Sockets Layer)協(xié)議用于對(duì)HTTP協(xié)議傳輸?shù)臄?shù)據(jù)進(jìn)行加密,從而就誕生了7a64e78988e69d8331333366306533HTTPS。

簡單來說,HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,要比http協(xié)議安全。
15. HTTPS 中的 SSL 握手建立過程
1、首先,客戶端 A 訪問服務(wù)器 B ,比如我們用瀏覽器打開一個(gè)網(wǎng)頁 https://www.baidu.com ,這時(shí),瀏覽器就是客戶端 A ,百度的服務(wù)器就是服務(wù)器 B 了。這時(shí)候客戶端 A 會(huì)生成一個(gè)隨機(jī)數(shù)1,把隨機(jī)數(shù)1 、自己支持的 SSL 版本號(hào)以及加密算法等這些信息告訴服務(wù)器 B 。
2、服務(wù)器 B 知道這些信息后,確認(rèn)一下雙方的加密算法,然后服務(wù)端也生成一個(gè)隨機(jī)數(shù) B ,并將隨機(jī)數(shù) B 和 CA 頒發(fā)給自己的證書一同返回給客戶端 A 。
3、 客戶端 A 得到 CA 證書后,會(huì)去校驗(yàn)該 CA 證書的有效性,校驗(yàn)方法在上面已經(jīng)說過了。校驗(yàn)通過后,客戶端生成一個(gè)隨機(jī)數(shù)3 ,然后用證書中的公鑰加密隨機(jī)數(shù)3 并傳輸給服務(wù)端 B 。服務(wù)端 B 得到加密后的隨機(jī)數(shù)3,然后利用私鑰進(jìn)行解密,得到真正的隨機(jī)數(shù)3。
4、最后,客戶端 A 和服務(wù)端 B 都有隨機(jī)數(shù)1、隨機(jī)數(shù)2、隨機(jī)數(shù)3,然后雙方利用這三個(gè)隨機(jī)數(shù)生成一個(gè)對(duì)話密鑰。之后傳輸內(nèi)容就是利用對(duì)話密鑰來進(jìn)行加解密了。這時(shí)就是利用了對(duì)稱加密,一般用的都是 AES 算法。
5、 客戶端 A 通知服務(wù)端 B ,指明后面的通訊用對(duì)話密鑰來完成,同時(shí)通知服務(wù)器 B 客戶端 A 的握手過程結(jié)束。
6、服務(wù)端 B 通知客戶端 A,指明后面的通訊用對(duì)話密鑰來完成,同時(shí)通知客戶端 A 服務(wù)器 B 的握手過程結(jié)束。SSL 的握手部分結(jié)束,SSL 安全通道的數(shù)據(jù)通訊開始,客戶端 A 和服務(wù)器 B 開始使用相同的對(duì)話密鑰進(jìn)行數(shù)據(jù)通訊。
到此,SSL 握手過程就講完了。可能上面的流程太過于復(fù)雜,我們簡單地來講:
客戶端和服務(wù)端建立 SSL 握手:客戶端通過 CA 證書來確認(rèn)服務(wù)端的身份;互相傳遞三個(gè)隨機(jī)數(shù),之后通過這隨機(jī)數(shù)來生成一個(gè)密鑰;互相確認(rèn)密鑰,然后握手結(jié)束;數(shù)據(jù)通訊開始,都使用同一個(gè)對(duì)話密鑰來加解密;
我們可以發(fā)現(xiàn),在 HTTPS 加密原理的過程中把對(duì)稱加密和非對(duì)稱加密都利用了起來。即利用了非對(duì)稱加密安全性高的特點(diǎn),又利用了對(duì)稱加密速度快,效率高的好處。
16. 中間人攻擊
中間人攻擊(英語:Man-in-the-middle attack,縮寫:MITM),指攻擊者與通訊的兩端分別創(chuàng)建獨(dú)立的聯(lián)系,并交換其所收到的數(shù)據(jù),使通訊的兩端認(rèn)為他們正在通過一個(gè)私密的連接與對(duì)方直接對(duì)話,但事實(shí)上整個(gè)會(huì)話都被攻擊者完全控制。

中間人攻擊過程

流程如下:
1、截獲客戶端與服務(wù)器通信的通道
2、然后在 SSL 建立連接的時(shí)候,進(jìn)行中間人攻擊
3、將自己偽裝成客戶端,獲取到服務(wù)器真實(shí)有效的 CA 證書(非對(duì)稱加密的公鑰)
4、將自己偽裝成服務(wù)器,獲取到客服端的之后通信的密鑰(對(duì)稱加密的密鑰)
5、有了證書和密鑰就可以監(jiān)聽之后通信的內(nèi)容了
17. charles抓包原理
抓取https包的時(shí)候,青花瓷會(huì)要求使用者 對(duì)抓包的設(shè)備(手機(jī)或其他設(shè)備)
,安裝一個(gè)證書,安裝這個(gè)證書的時(shí)候,其實(shí)是安裝了一個(gè)根證書(允許頒發(fā)CA的一個(gè)證書機(jī)構(gòu)的根證書),當(dāng)你安裝了該根證書之后,該證書機(jī)構(gòu)頒發(fā)的其他證書,默認(rèn)都會(huì)被你的系統(tǒng)所信任,這個(gè)就是青花瓷完成https抓包的一個(gè)重要前提!!

[圖片上傳失敗...(image-a62461-1592965813713)]

中間人攻擊示意圖

1、當(dāng)客戶端Client對(duì)服務(wù)器Server發(fā)送請(qǐng)求(帶著隨機(jī)數(shù)和加密算法),由于青花瓷做了代理,請(qǐng)求被青花瓷攔截,處理(青花瓷的角色現(xiàn)在對(duì)于Client來說是服務(wù)器),青花瓷將客戶端帶的隨機(jī)數(shù)和加密算法處理,然后返回自己的證書通過客戶端校驗(yàn),獲取到客戶端提交的請(qǐng)求參數(shù)等數(shù)據(jù),
2、青花瓷作為客戶端(自己去產(chǎn)生隨機(jī)數(shù)和攜帶支持的加密算法)去請(qǐng)求剛剛Client想要請(qǐng)求的Server,然后,Server會(huì)和青花瓷完成上面講的那個(gè)完整的校驗(yàn),并且讀取青花瓷帶錯(cuò)來的具體請(qǐng)求,返回正常的數(shù)據(jù)結(jié)果.
3、青花瓷得到服務(wù)器數(shù)據(jù)的返回結(jié)果之后,開始繼續(xù)和過程1中的Client以服務(wù)器的身份,去做處理,首先收到客戶端的隨機(jī)數(shù)和加密算法,自己生成一個(gè)隨機(jī)數(shù)和選擇一個(gè)客戶端的加密算法,然后*********重要********** 青花瓷會(huì)返回一個(gè)偽造的CA證書(公鑰和真實(shí)的server不一樣,但是域名是一樣的,或者說,除了域名是一致的,其他的都不是一致的,而且這個(gè)簽發(fā)機(jī)構(gòu)是青花瓷之前讓你安裝的根證書 簽發(fā)的,所以,當(dāng)返回這個(gè)證書的時(shí)候,你的客戶端的信任鏈?zhǔn)强梢酝瓿傻?會(huì)被系統(tǒng)信任),然后Client在這個(gè)偽造的證書(對(duì)于青花瓷和Client是真實(shí)證書(驗(yàn)證信任鏈和證書信息都通過了),但是和真實(shí)的域名對(duì)應(yīng)的證書來看,是偽造證書)的基礎(chǔ)上,和青花瓷通信,然后青花瓷再和Server通信,成了一個(gè)中間人的角色,這樣,整個(gè)過程的數(shù)據(jù)傳輸,都被青花瓷給監(jiān)聽到了
在此,中間人攻擊的過程 就完成了
10. 算法
1. 算法字符串翻轉(zhuǎn)(頭條二面、騰訊一面)
2. 兩個(gè)鏈表找第一個(gè)相同結(jié)點(diǎn)(騰訊一面)
3. 找鏈表的倒數(shù)第k個(gè)結(jié)點(diǎn)(騰訊一面)
4. 把一個(gè)鏈表比某個(gè)值大的放在左邊,比它小的放在右邊(騰訊一面)
5. 二叉樹的中序遍歷,非遞歸(騰訊一面)
6. 求數(shù)組的最長子數(shù)組(百度一面)
7. 在一個(gè)10G的數(shù)據(jù)里面找出最大的100個(gè)數(shù)(百度二面)

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

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