博客連接javascript
基本數據類型html
// 整數 byte 1 short 2 int 4 long 8 // 浮點數 float 4 double 8 // 邏輯 boolean 1 // 字符 char 2, Unicode
引用類型的變量, 在堆, 變量只是引用, 相似於指針, 只能指向特定對象, 不能亂指, 複製變量的時候, 複製的是引用前端
引用類型: 數組, 類, 接口vue
抽象類跟接口的區別java
JavaNotesnode
抽象類和接口的區別python
抽象類, 是聲明, 抽象類不能instantiate(實例化), 也就是不能製造對象。抽象方法只聲明, 不實現。具體的實現由繼承它的子類來實現。linux
public abstract class Shape{ // 抽象的方法, 注意沒有大括號, ()後面直接分號結尾 // 有abstract方法的類必須是abstract public abstract void draw(); }
接口, 讓其餘類可以有接口的方法ios
public interface Cell{ // 不須要顯示寫abstract void draw(Graphics g, int x, int y, int size); } public class Fox extends Animal implements Cell{ @Override public void draw(...){ // ... } public void run() { } }
抽象類能夠有非抽象的方法(具體實現), 接口是純抽象類, 只有抽象方法git
一個子類只能存在一個父類, 可是能夠存在多個接口。
M, Model, 模型, 保存和維護數據, 還能夠 通知 View 進行界面的更新.
V, View, 表現, 從 Model 得到數據, 並以此畫出表現(界面). View 是被動的, 只有在 Model 通知 View 以後, View纔會去Model取數據, 並畫出來.
C, Control, 控制, 獲得用戶輸入, 以此調整數據. C 和 V 並不直接交互. C只能更新Model中的數據, 也就是說, 用戶在界面上所做的操做, 不會直接修改界面上的顯示. 而是先去修改後臺的數據, 再由Model通知View, 再總體重畫.
start(), run(), stop(), destroy()
新建 --- 就緒 --- 運行 --- 阻塞 --- 運行 --- 終止
分類
ArrayIndexOutOfBoundsException OpenFileException AllocateMemoryException LoadFileException OutOfMemoryError
處理方式
try{ } catch(ArrayIndexOutOfBoundsException e){ }
某個對象在將來的程序運行中, 將不會被訪問, 就能夠回收它的內存
引用計數收集器, 當有其餘數據與其相關時則加一, 反之相關解除時減一, 最後計數爲 0 的對象能夠回收
跟蹤收集器, 按期對若干根儲存對象開始遍歷, 對與其相關的對象進行標記, 最後, 沒有被標記的對象就能夠回收
局部變量, 函數參數
全局變量, 靜態全局變量, 靜態局部變量
若沒有手動初始化, 則會自動初始化爲0
new --- delete / malloc --- free
存放字符串常量和const修飾的全局變量
預處理 --- 編譯 --- 彙編 --- 連接 --- 裝載 --- 運行
malloc, 分配內存, 是在 運行
這一階段。即在 heap 上動態分配
指向二維數組的指針
int a[4][2]; int (*p) [2]; p = a; p[3][1];
[]
的優先級高於 *
, 因此要加括號
二級指針
void getMemory(char **p){ *p = (char *)malloc(100); } int main(){ char *str = NULL; getMemory(&str); strcpy(str, "Thurs"); strcat(str+2, " day"); printf("%s\n", str); return 0; }
首先 str
被分配了100字節的空間, 而後在 str 開頭粘貼了 Thurs
, 接着, 因爲 strcat
老是先找到末尾再粘貼, 因此 day
不會覆蓋 urs
正數與原碼和反碼相同。對於負數, 以 -1
爲例
1)先寫出原碼, `1000 0001` 2)符號位不變, 其他各位取反, `1111 1110` 3)最後 +1, `1111 1111`
數據類型在內存中的表達形式
整數:二進制數(補碼), 能夠直接在加法器裏面作加法 浮點數:要進行編碼
結構體內定義指針
typedef struct{ int val; struct Node *lchild, *rchild; }Node; Node root = {1, NULL, NULL};
struct node{ int val; struct Node *lchild, *rchild; }; struct node root = {1, NULL, NULL};
const
在 *
以前, 意思是對 i
只讀
/* const 在 * 以前, 意思是 對 i 只讀 ** 能夠經過 *p 讀取i的值, 但不能經過 *p 修改i的值 ** 另外, 指針做爲函數參數時, 這樣寫 (const int * p) */ int i = 1; const int * p1 = &i; int const * p2 = &i;
const 在 * 的後面, 意思是 指針 不能指向其餘地址
/* const 在 * 的後面, 意思是 指針 不能指向其餘地址 ** p3 被綁定到了 j, 就沒法再指向其餘地址 ** 能夠經過p3來讀寫j的值 */ int j = 2; int * const p3 = &j; *p3; // ok *p3 = 3; // ok int k = 123; p3 = &k; // error
用法
int *a = (int *)malloc( 10*sizeof(int) )
man malloc
能夠看到參數要求是(size_t size)
, 因此實參是(10*sizeof(int))
, 表示申請到了10*4=40
個字節的空間, 一樣的也能夠40*sizeof(char)
, 或者直接寫40
能夠看到返回類型是 void *
, 這也就解釋了爲何要在前面加上(int *)
, 由此劃分空間, 來區分類型
sizeof()
是靜態的, 程序編譯完成後已經定下來, 直接填進去了, 並不會真的去作計算
int a = 1; printf("%d\n", sizeof(a++)); // 4 printf("%d\n", a); // 1, sizeof()是靜態的, 程序編譯完成後已經定下來, 直接填進去了, 並不會真的去作a的++ printf("%d\n", sizeof(a + 2.0));// 8, 已經轉換成了double printf("%d\n", sizeof(double)); // 8 return 0;
define
宏是在預處理階段展開, const
常量是編譯運行階段使用.
define宏沒有類型, 不作任何類型檢查, 僅僅是展開. const常量有具體的類型, 在編譯階段會執行類型檢查.
define宏僅僅是展開, 有多少地方使用, 就展開多少次, 不會分配內存. const常量會在內存中分配(堆或棧).
==
做爲判斷條件virtual
的函數叫作虛函數用於 多態
(即 動態綁定
, 覆蓋Override
, 運行的時候根據實例對象來調用方法)
class Animal { public: void run(){ cout << "That animal is running\n"; } virtual void eat(){ cout << "That animal is eating\n"; } }; class Dog : public Animal{ public: void run(){ cout << "The dog is running\n"; } void eat(){ cout << "The dog is eating\n"; } }; int main(){ // 父類 `Animal` 類型的 `指針` 能夠管理子類對象 // 若是方法名前面有 virtual, 則能夠動態綁定 Animal * animal = new Dog(); animal->run(); // That animal is running, 隱藏子類方法 animal->eat(); // The dog is eating, 子類方法覆蓋父類, 多態 // 注意指針才能夠, 普通變量形式仍然會隱藏子類方法 Animal ani = Dog(); ani.eat(); // That animal is eating, 隱藏子類方法 return 0; }
父類方法被聲明爲 virtual
後, 直接/間接子類中的這個方法都會變成 virtual
, 也即子類中的 virtual
能夠省略, 但最好仍是寫上去
純虛函數只有聲明, 沒有實現, 至關於接口規範。含有純虛擬函數的類稱爲抽象類, 它不能生成對象(不能放在等號右邊), 但能夠聲明指向實現該抽象類的具體類的指針或引用。
class Flyable { public: virtual void fly() = 0; // 純虛函數, 只有聲明, 後接 = 0 virtual void run() = 0; }; class Bird : public Flyable{ public: void fly(){ cout << "Bird can fly\n"; // 子類只有實現純虛函數才能實例化 } }; class Superman : public Flyable{ public: void fly(){ cout << "Superman can fly\n"; } void run(){ cout << "Superman is running\n"; } }; int main(){ Flyable * f1 = new Bird(); f1->fly(); // 出錯, 由於沒有實現全部的純虛函數, 因此仍然是抽象類, 沒法實例化 Flyable f2 = new Superman(); f2->fly(); // Superman can fly return 0; }
定義純虛函數的目的在於, 使派生類僅僅只是繼承函數的接口。純虛函數的意義, 讓全部的類對象(主要是派生類對象)均可以執行純虛函數的動做, 但類沒法爲純虛函數提供一個合理的缺省實現。因此類純虛函數的聲明就是在告訴子類的設計者, 「你必須提供一個純虛函數的實現, 但我不知道你會怎樣實現它」。
new
操做符內存分配成功時, 返回的是對象類型的指針, 類型嚴格與對象匹配, 無須進行類型轉換, 故 new
是符合類型安全性的操做符。而 malloc
內存分配成功則是返回 void *
, 須要經過強制類型轉換將 void *
指針轉換成咱們須要的類型。
類型安全很大程度上能夠等價於內存安全, 類型安全的代碼不會試圖方法本身沒被受權的內存區域。關於 C++
的類型安全性可說的又有不少了
+
運算符,從新申請 len1 + len2
的內存空間,而後把 s1, s2
複製進去選擇器
// 按ID查找 document.getElementById('xxx'); // 按tagname查找 document.getElementsByTagName('xxx'); // classname document.getElementsByClassName('xxx');
jQuery, 選擇器是 jQuery
的核心
// DOM 操做 var ele = document.getElementById('id1'); var divlist = document.getElementsByTagName('div'); // jQuery 的寫法 // 返回一個 jQuery 對象, 即若 id1 存在, 那麼返回 [<div id="id1">...</div>] // 若不存在, 則返回 [] var ele = $('#id1'); // jQuery 對象和 dom 對象相互轉化 var eledom = ele.get(0); ele = $(eledom); // 按 class 查找 var a = $('.red.green'); // 多個 class 時中間沒有空格 // 按屬性查找 var email = $('[name=email]'); // 找出<??? name="email"> var passwordInput = $('[type=password]'); // 找出<??? type="password"> var icons = $('[name^=icon]'); // 找出全部name屬性值以icon開頭的DOM var names = $('[name$=with]'); // 找出全部name屬性值以with結尾的DOM // 組合查找 var emailInput = $('input[name=email]'); // 找到全部 input 中的 name="email" 的屬性 // 不會找出 <div name="email"> // 多項選擇器(不會重複選擇) $('p,div'); // 把<p>和<div>都選出來 $('p.red,p.green'); // 把<p class="red">和<p class="green">都選出來
正則表達式
`\d` 數字 `\w` 字母或數字 `.` 至少 1 個任意字符 `*` 至少 0 個任意字符 `\d{3}` 匹配 3 個字符 `[0-9a-zA-Z\_]` 匹配一個數字, 字母或者下劃線 var re1 = /^\d{11}$/; re1.test('12345678'); // false
AJAX, Asynchronous JavaScript and XML, 意思就是用 JavaScript 執行異步網絡請求
AJAX請求是異步執行的, 也就是說, 要經過回調函數得到響應
function success(text) { var textarea = document.getElementById('test-response-text'); textarea.value = text; } function fail(code) { var textarea = document.getElementById('test-response-text'); textarea.value = 'Error code: ' + code; } var request = new XMLHttpRequest(); // 新建XMLHttpRequest對象 request.onreadystatechange = function () { // 狀態發生變化時, 函數被回調 if (request.readyState === 4) { // 成功完成 // 判斷響應結果: if (request.status === 200) { // 成功, 經過responseText拿到響應的文本: return success(request.responseText); } else { // 失敗, 根據響應碼判斷失敗緣由: return fail(request.status); } } else { // HTTP請求還在繼續... } } // 發送請求: request.open('GET', '/api/categories'); request.send();
引用計數, del對象
Unix/Linux
推薦多進程, 提供了一個 fork()
系統調用(System call
)
pid = fork()
, 調用一次返回兩次, 子進程中返回的 pid == 0
, 父進程中返回的是子進程的 pid > 0
, ppid = getppid()
能夠獲得父進程的 pid
import os # 獲得當前進程的 pid print( os.getpid() ) pid = os.fork() if pid == 0: print('This is child process %s, parent is %s' % (os.getpid(), os.getppid())) else: print('This is parent process %s, child is %s' % (os.getpid(), pid))
結果
17420 This is parent process 17420, child is 17421 This is child process 17421, parent is 17420
Windows
沒有 fork()
, Python
多進程須要使用 multiprocessing
from multiprocessing import Process import os def proc(name): print('child process %s, pid = %s' % (name, os.getpid())) p = Process( target=proc, args=('test',) ) print('child process start') p.start() p.join() print('child process end')
結果
child process start child process test, pid = 17491 child process end
建立子進程時, 只須要傳入待執行函數 target
和函數的參數, 建立一個 Process
實例, 用 start()
方法啓動
join()
方法能夠等待子進程結束後再繼續往下運行, 一般用於進程間的同步。
多線程. 進程是由若干線程組成的, 一個進程至少有一個線程, 線程是操做系統直接支持的基本執行單元.
啓動一個線程就是把一個函數傳入並建立 Thread
實例, 而後調用 start()
開始執行
import time, threading def loop(): print('%s is running' % threading.current_thread.name) print( '%s is running' % threading.current_thread().name ) t = threading.Thread(target=func, name='myThread') t.start() t.join() print( '%s ended' % threading.current_thread().name )
多線程共享的內容: 虛擬地址空間,只讀代碼塊,讀、寫數據, 堆(全局, 靜態), 打開的文件集合
鎖
balance = 0 def change_balance(n): global balance balance += n balance -= n lock = threading.lock() def run_thread(n): for i in range(10000): # 用以前先得到 balance 等全局變量的獨佔權 lock.acquire() try: change_balance(n) finally: # 用完後釋放鎖 lock.release()
Python 動態類型語言, 運行期間才檢查數據類型
Java 分號結尾, Python 不須要
結構定義
struct Node{ public: int val; Node * next; Node(int x) : val(x), next(NULL) {} };
插到第 n 個結點前面, n 從 0 開始
Node * insertBefore(Node * head, int n, int val){ Node * p = head; Node * node = new Node(val); if( n == 0 ){ node->next = head; head = node; } else{ --n; while( p != NULL && n > 0 ){ p = p->next; --n; } node->next = p->next; p->next = node; } return head; }
插到第 n 個結點後面, n 從 0 開始
Node * insertAfter(Node * head, int n, int val){ Node * p = head; Node * node = new Node(val); while( p != NULL && n > 0 ){ p = p->next; --n; } node->next = p->next; p->next = node; return head; }
刪除第 n 個結點, n 從 0 開始
Node * deleteAt(Node * head, int n){ if( head == NULL ){ return head; } if( n == 0 ){ Node * now = head->next; delete head; return now; } --n; Node * pre = head; Node * now = head->next; while( now != NULL && n > 0 ){ now = now->next; pre = pre->next; n--; } if( now != NULL ){ pre->next = now->next; delete now; } return head; }
功能、性能、空間開銷的折中結果。
AVL更平衡,結構上更加直觀,時間效能針對讀取而言更高;維護稍慢,空間開銷較大。
紅黑樹,讀取略遜於AVL,維護強於AVL,空間開銷與AVL相似,內容極多時略優於AVL,維護優於AVL。
若是插入一個node引發了樹的不平衡,AVL和RB-Tree都是最多隻須要2次旋轉操做,即二者都是O(1);可是在刪除node引發樹的不平衡時,最壞狀況下,AVL須要維護從被刪node到root這條路徑上全部node的平衡性,所以須要旋轉的量級O(logN),而RB-Tree最多隻需3次旋轉,只須要O(1)的複雜度。
其次,AVL的結構相較RB-Tree來講更爲平衡,在插入和刪除node更容易引發Tree的unbalance,所以在大量數據須要插入或者刪除時,AVL須要rebalance的頻率會更高。所以,RB-Tree在須要大量插入和刪除node的場景下,效率更高。天然,因爲AVL高度平衡,所以AVL的search效率更高。
map的實現只是折衷了二者在search、insert以及delete下的效率。整體來講,RB-tree的統計性能是高於AVL的。
紅黑樹是 BST,且有以下規則
1) 結點是紅色或黑色 2) 根是黑色 3) 葉子是黑色結點(葉子是 NULL) 4) 紅結點必有兩個黑色孩子,也即,從根到葉子路徑上不能有連續的紅結點 5) 任一結點向下到葉子的全部路徑都包含相同數目的黑色節點(黑高度相同)
遞歸查找LCA
// LeetCode 235, 236 都適用 TreeNode * lowestCommonAncestor(TreeNode * root, TreeNode * p, TreeNode * q){ if( root == NULL || root == p || root == q ){ return root; } TreeNode * left = lowestCommonAncestor(root->left, p, q); TreeNode * right = lowestCommonAncestor(root->right, p, q); if( left != NULL && right != NULL ){ return root; } else{ return left==NULL ? right : left; } }
冒泡, 最好 O(n), 最壞 O(n^2)
// 升序 void bubble_sort(int a[], int len){ for(int i=0; i < len; i++ ){ for( int j = len - 1; j > i; j-- ){ if( a[j] < a[j-1] ){ swap(a[j], a[j-1]); } } } } int main(){ const int len = 8; int a[len]={4, 2, 5, 1, 3, 2, 5, 1}; bubble_sort(a, len); for( int i = 0; i < len; i++){ cout << a[i] << '\t'; } return 0; }
快排, 最壞 O(n^2), 平均 O(nlgn)
int a[MAXSIZE] = {4, 2, 6, 3, 1, 5, 7}; int partQuickSort(int left, int right){ int i = left, j = right; int key = a[i]; while( i < j ){ while( i < j && a[j] > key ){ j--; } if( i < j ){ // a[j] < key, 換到左邊 a[i++] = a[j]; } while( i < j && a[i] < key ){ i++; } if( i < j ){ // a[i] > key, 換到右邊 a[j--] = a[i]; } } int mid = i; a[mid] = key; return mid; } /* 以a[left]爲中軸key, 把全部小於key的都放到它的左邊, 大的放到右邊。 中軸的位置就固定了。 再對左邊這一塊和右邊這一塊, 作一樣的處理。 */ void quickSort( int left, int right ){ if(left < right){ int mid = partQuickSort(left, right); quickSort(left, mid - 1); quickSort(mid + 1, right); } }
插入, 最好 O(n), 最壞 O(n^2)
// 升序 void insert_sort(int a[], int len){ for(int i = 1; i < len; i++ ){ int j = i; int key = a[j]; // 把 key 插到正確的位置 while( j > 0 && a[j-1] > key ){ a[j] = a[j-1]; j--; } a[j]=key; } }
二分, 序列必須有序
// 遞歸 int bsearch(int a[], int left, int right, int key){ if( left <= right ){ int mid = (left + right) / 2; if( key < a[mid] ){ return bsearch(a, left, mid - 1, key); } else if( key > a[mid] ){ return bsearch(a, mid + 1, right, key); } else{ return mid; } } return -1; } // 非遞歸 int bsearch(int a[], int left, int right, int key){ while( left <= right ){ int mid = (left + right) / 2; if( key < a[mid] ){ right = mid - 1; } else if( key > a[mid] ){ left = mid + 1; } else{ return mid; } } return -1; }
最大公因數 gcd, 最小公倍數 lcm
// PAT_B_1062, 1034, PAT_A_1081 // 最大公因數, the Greatest Common Divisor int get_gcd(int a, int b){ if( b == 0 ){ return a; } else{ return get_gcd(b, a % b); } } // 最小公倍數, the Lowest Common Multiple int get_lcm(int a, int b){ int gcd = get_gcd(a, b); if( gcd != 0 ){ return a * b / gcd; } else{ return 0; } }
數據庫事務(Transaction)的 ACID 特性
原子性(Atomicity), 一致性(Consistency), 隔離型(Isolation), 持久性(Durability)
數據庫事務隔離級別有4個
# 由低到高依次爲 Read uncommitted, 讀到了未提交的事物, 只是 add 尚未 commit Read committed, 讀到了上一次的commit, 也就是說尚未更新 最新的commit Repeatable read, 保證讀取最新的 commit, 爲此, 讀取的時候不容許提交 Serializable, 要求有很高的實時同步性 # 這四個級別能夠逐個解決髒讀 、不可重複讀 、幻讀 這幾類問題
數據結構, 對數據的操做, 完整性約束
Create, Read, Update, and Delete
過程
1.首先鏈接到數據庫 conn = sqlite.connect('test.db') 2.創建遊標 cursor cursor = conn.cursor() 3.創建表 create table user (id int, name varchar(20), score int ) 4.insert into 插入數據, 注意佔位符是 ? insert into user (id, name) values(1, "Alice", 88) insert into user (id, name) values(2, "Bob", 89) insert into user (id, name) values(3, "Cindy", 88) 5.select * from user where 查找數據 select * from user where id between 1 and 3 order by score asc 6.cursor.close() 7.conn.commit() 8.conn.close()
column, 列, 字段
select * from user select col1, col2 from user
下面以這個表格 customers
爲例, 展現 SQL 的語法
id | name | age | city | postalcode | country |
1 | Alfreds | 25 | Berlin | 12209 | Germany |
2 | Ana | 15 | Mexico | 05021 | Mexico |
3 | Antonio | 20 | Mexico | 05023 | Mexico |
4 | Thomas | 30 | London | WA11DP | UK |
5 | Berglunds | 35 | Lulea | S-958-22 | Sweden |
where 條件選擇
select * from customers where country='Germany' and city='Berlin'
order by 排序
select * from customers order by country
插入
insert into customers (name, age, city, postalcode, country) values ('Bart', 10, 'LA', '4006', 'USA')
更新
update customers set name = 'Smith', city = 'Paris' where id = 5
刪除
delete from customers where name = 'Berglunds'
limit/top 不返回所有結果, 只返回有限數量的記錄
# SQL select top 3 from customers # MySQL select * from customers limit 3
最大最小值
select min(age) from customers
統計 count, distinct
# 統計有多少個不一樣的國家 select count(distinct country) from customers
平均值
select avg(age) from customers
求和
select sum(age) from customers
通配符
# SQL select * from customers where name like 'B%' # sqlite select * from customers where name like 'B*'
選擇範圍
# 離散 select * from customers where country in ('Germany', 'France') # 連續 select * from customers where age between 10 and 20
鏈接表格
inner join, (A ∩ B) left join, (A ∩ B) U A right join, (A ∩ B) U B full outer join, (A U B)
2xx: Successful responses
3xx: Redirection messages
This response code means that the URI of the requested resource has been changed permanently. Probably, the new URI would be given in the response.
4xx: Client error responses
This response means that server could not understand the request due to invalid syntax.
The client does not have access rights to the content, i.e. they are unauthorized, so server is rejecting to give proper response. Unlike 401, the client's identity is known to the server.
The server can not find requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 to hide the existence of a resource from an unauthorized client. This response code is probably the most famous one due to its frequent occurence on the web.
The request method is known by the server but has been disabled and cannot be used. For example, an API may forbid DELETE-ing a resource. The two mandatory methods, GET and HEAD, must never be disabled and should not return this error code.
5xx: Server error responses
The server has encountered a situation it doesn't know how to handle.
The request method is not supported by the server and cannot be handled. The only methods that servers are required to support (and therefore that must not return this code) are GET and HEAD.
https://developer.mozilla.org...
GET爲請求數據, 沒有反作用, 每次請求的效果都相同。
POST爲修改數據, 相對GET來說沒有那麼安全(由於要修改數據)。
GET 經過 URL 傳輸數據, 容易在日誌記錄中留下私密數據, 隱蔽性沒有POST好。
通常經過GET方式傳輸數據, 因爲Web Server和瀏覽器限制, URL長度限制傳輸的數據有限(根據Web Server配置和瀏覽器不一樣, 通常爲2kB~8kB)
而POST一般能夠忽略限制(實際上根據Web Server配置也仍是有限制的, 通常是2G)
http://stackoverflow.com/ques...
過程
<br>
B
在第一次收到 A
的 SYN
以後, 沒有馬上進入 ESTABLISHED
, 而是等到 A
再來一次 ACK
才創建鏈接, 爲何要這樣設計?答:防止已經失效的鏈接請求(好比在某個網絡滯留了好久), 忽然又傳到了 B
, 從而產生錯誤, 形成 B
的資源浪費.
考慮這樣一種狀況: A
的第一次 SYN
被攔截了。而後 A
又發了一次 SYN
, B
收到, 而且完成後續的 握手 --- 數據傳輸 --- 揮手
。
此時 A
的第一次 SYN
又被放了出來, 並傳到 B
, 若是隻須要 2
次握手, 那麼此時 B
就會直接進入 ESTABLISHED
而這個時候 A
都已經關機了, 不會發數據過來了, B
就在 ESTABLISHED
中苦苦等待 A
, 浪費不少資源。
若是是3次握手, 那麼 B
只會進入 SYN-RCVD
狀態, 一段時間後 (比 ESTABLISHED
要短, 並且不會佔用那麼多資源), 會自動取消鏈接
SYN Flood
是一種廣爲人知的 DoS
(拒絕服務攻擊) , 是 DDoS
(分佈式拒絕服務攻擊) 的方式之一, 這是一種利用 TCP
協議缺陷, 發送大量僞造的 TCP
鏈接請求, 從而使得被攻擊方資源耗盡 (CPU
滿負荷或內存不足) 的攻擊方式。
假設一個用戶向服務器發送了 SYN
報文後忽然死機或掉線, 那麼服務器在發出 SYN+ACK
應答報文後是沒法收到客戶端的 ACK
報文的 (第三次握手沒法完成) ,
這種狀況下服務器端通常會重試 (再次發送 SYN+ACK
給客戶端) 並等待一段時間後丟棄這個未完成的鏈接, 這段時間的長度咱們稱爲 SYN Timeout
, 通常來講這個時間是分鐘的數量級 (大約爲30秒 - 2分鐘).
一個用戶出現異常致使服務器的一個線程等待1分鐘並非什麼很大的問題, 可是, 若是有一個惡意的攻擊者大量模擬僞造這種狀況, 服務器端將會維護一個很是大的半鏈接列表, 從而消耗很是多的資源
數以萬計的半鏈接, 即便是簡單的保存並遍歷也會消耗很是多的 CPU
時間和內存, 況且還要不斷對這個列表中的 IP
進行 SYN+ACK
的重試
實際上若是服務器的 TCP/IP
棧不夠強大, 最後的結果每每是堆棧溢出崩潰,
即便服務器端的系統足夠強大, 服務器端也將忙於處理攻擊者僞造的 TCP
鏈接請求而無暇理睬客戶的正常請求 (畢竟客戶端的正常請求比率很是之小) , 此時從正常客戶的角度看來, 服務器失去響應, 沒法對正常客戶進行服務
這就是 SYN Flood
攻擊
防護措施: 縮短 SYN Timeout
, 增長 IP
黑名單, 使用 CDN
A
發出的最後一個 ACK
可能會丟失. 而此時 B
還在等待這個 ACK
, 若是 B
一直沒有收到, 則會給 A
發一個 FIN + ACK
, 通知 A
剛纔那個沒收到, 從 A
發出 ACK
到 B
發出 FIN + ACK
須要 2MSL
, 若是 2MSL
時間裏面 A
都沒有收到 B
的回覆, 就認爲本身的 ACK
已經送達 B
, 因此 A
能夠安心關閉了
並且, 2MSL
後, 可使本次鏈接所產生的全部報文段都從網絡上消失 (TTL, Time To Live
), 之後創建新的鏈接, 就不會和舊的鏈接混淆
Intent
交互圖
http://www.ruanyifeng.com/blo...
1). Client 給出協議版本號、一個的隨機數(Client random),以及客戶端支持的加密方法。 2). Server 確認雙方使用的加密方法,並給出數字證書,以及一個服務器生成的隨機數 3). Client 確認數字證書有效,而後生成一個新的隨機數(Premaster secret), 並使用數字證書中的公鑰,加密 Premaster secret, 發給 Server 4). Server 使用本身的私鑰,獲取愛麗絲髮來的隨機數 Premaster secret 5). Client 和 Server 根據約定的加密方法,使用前面的三個隨機數,生成"對話密鑰"(session key),用來加密接下來的整個對話過程。 生成對話密鑰一共須要三個隨機數。 握手以後的對話使用"對話密鑰"加密(對稱加密),服務器的公鑰和私鑰只用於加密和解密"對話密鑰"(非對稱加密),無其餘做用。 服務器公鑰放在服務器的數字證書之中。
最重要的緣由在於吊銷。當網站的私鑰丟失時,網站應該向證書頒發機構(CA)申請將他們的證書加入到證書吊銷列表(CRL)裏。當用戶訪問https站點時,瀏覽器會自動向CA請求吊銷列表,若是用戶訪問的站點提供的證書在CRL裏,瀏覽器就不信任這個證書,由於攻擊者可能擁有一樣的證書。因此若是證書永久有效,隨着愈來愈多的私鑰丟失,吊銷列表也愈來愈大(由於只有加進去的,沒有剔出去的),這既給CA增長流量壓力,也會增長瀏覽器的流量。而一旦有效期只有幾年,那麼CA就能夠將那些已通過期了的證書從CRL裏剔除,由於反正瀏覽器也不信任過時證書。
https://segmentfault.com/a/11...
客戶端和服務器之間用於傳輸HTTP數據的TCP鏈接不會關閉, 若是客戶端再次訪問這個服務器上的網頁, 會繼續使用這一條已經創建的鏈接
javascript, setTimeout() 的用法
console.log(1) for( let i = 0; i < 5; i++ ){ setTimeout(function(){console.log(2);}, 1000); } console.log(3);
輸出是什麼(1 3 2 2 2 2 2)
異步, 不會等
https://www.liaoxuefeng.com/w...
axios, jQuery, AJAX 是怎麼寫的
體系結構, 操做系統, 網絡, 語言, 數據結構算法, 框架, 應用
若是要作 Java 就專攻 Java, SSM/SSH 實踐好, 理解好