owned this note
owned this note
Published
Linked with GitHub
---
robots: index, follow
tags: NCTU, CS, 共筆
description: 交大資工課程學習筆記
lang: zh-tw
dir: ltr
breaks: true
disqus: calee
GA: UA-100433652-1
---
網路程式設計 -- 吳毅成
===
## Syllabus
- 吳毅成
- http://java.csie.nctu.edu.tw/~icwu/
- email: icwu@csie.nctu.edu.tw
- 使用 git 版控及交作業 (用 [Bitbucket](https://bitbucket.org/))
- 分數(take 2015 score as example)
- 1 HW (6%)
- 4 project (22%, 21%, 17%, 12%) (2 week for each)
- 1 Final (21%)
- 投影片: 四樓影印室找小姐拿
- 會寫到 Unix programming & Windows programming
## Summary
- BSD Socket
- Flow
- Introduction
- Unix Programming (用 C/Cpp -> 看到底層)
- Share memory
- Network primer
- Berkeley Socket -> 第一個 project
- Socket Programming Paradigms
- Iterative Servers
- Concurrent Servers
- Single-Process Concurrent Servers
- Multi-services Servers
- Server issues
- Concurrent Clients -> 第二個 project (Game Server)
- Internet and Distributed Information Systems
- HTTP, CGI
- FastCGI
- Winsock & Asyncsock -> 第三個 project (HTTP Server)
- Thread vs. Select
- Cookie, i18n, C10K
- Web, PHP, i18n
- Case Studies
- Firewalls
- P2P -> 第四個 project (SOCKS Server, 有點像 proxy)
- RPC (Remote Procedure Call)
## Unix Programming
- 基本指令 (歡迎修 SA)
- C function
- main(argc, argv, envp)
- argc: int (參數數目)
- argv: char*[] (參數位址)
- envp: char*[] (環境)
- fork 程式後,才去執行 fork 的程式
- 進入 main 之前,會先去執行 initializion (類似 construction 的地方)
- 程式執行時 stack 會先塞 argc,argv,envp,然後跳到 start,然後才跳到 main
- 程式結束時,照 stack 順序跳出 -> call `exit` -> call `_exit`
- 可以在任何地方 call `exit` (如果總是要照 stack 跳,有時候反而會比較麻煩)
- environment list
```C=
main(argc, argv, envp)
int argc;
char *argv[];
char *evnp[];
{
int i;
for (i = 0; envp[i] != (cahr*) 0; i++)
printf("%s\n", envp[i]);
exit(0);
}
```
- output 會跟 UNIX 的 `printenv` 很像
- 後來發現很少人用,所以可以拔掉 (還是可以用 `getenv("PATH")` 之類的抓)
- Process
- compile 就該有的 data
- text
- initialized read-only data: 不可被修改的 (ex. 程式本身[debat: 程式到底可否改變自己], printf("%d") 的 %d)
- initialized read-write data: 可被修改的
- 非 compile 出來的
- unintialized data
- heap 從下面長上去
- stack 從上面長下來
- **如果是 mutithread 時?!** => 需要小心設計
- stack 需要切多大?
- Kernel & Process
- 維護資訊
- keep track of process
- start & stop & restart & reload
- Process table
- Process ID(PID)
- $0$:
- $1$:
- $2$:
- $3$~$2^{32}-1$
- User & Group
- `/etc/passwd`: vipw, getuid()
- `/etc/shadow`
- `/etc/group`: vigr, getgid()
- 權限
- chown
- chmod: rwx, 777
- 密碼
- passwd
- Effective
- effective user = real user
- 可是在做動作時,可以用 seteuid 之類的方法,可以改權限
- chmod (s)
- ex. sudo
- 參考: [ID 分類](https://zh.wikipedia.org/wiki/%E7%94%A8%E6%88%B7ID#.E5.88.86.E7.B1.BB)
- File
- [File Descriptor Table](https://en.wikipedia.org/wiki/File_descriptor) (fdtable)
- 每一個 file 只是一個 index id,會 point 到固定的資料結構
- 
- table 的前三個會固定給 stdin, stdout, stderr
- 在程式剛跑起來的時候,理論上應該只有前三個,若 table 上還有殘留其他檔案,應該是程式寫爛了 XD
- open("file") 就是在 table 裡繼續加入下去 (open 是 system call)
- system call != function call
- system call 是用 interupt 去摳 kernel,所以組語裡是不會用一般 function call 的方式執行
- close 將 table 的 index 拔掉,並清掉 allocate 出來的 file 所在的 memory
- read/write(file_table_index, buffer_address, buffer_size) 都是 kernel 負責處理的
- fcntl:
- ioctl:
- lseek: 往前看
- dup: copy address => 讓指向同一個位置
- 可以用 `>` or `>>` or `<` or `<<` 來作重導向(stdout, stdin 都是 file)
- 因為設計時忠於 input, output,可以在用檔案結構重導向到新的地放 ex. cat a.cpp > b.cpp
- Signal Model
- 
- 當程式執行到中間,突然傳一個 signal 出來作其他事情
- ex. Ctrl-C
- 傳入 Interrupt/trap,會馬上轉換身分從 user => supervise mode,跳到 kernel 裡,然後透過 trap table 跳到 kernel 中相對應的指令位址,**得到 kernel 程式位址後,還要先降權到 user mode,再執行這個 program(確保用 user mode 執行這個程式)** ,執行完後在回到原來的程序繼續執行
- 重點在跳到 kernel 的動作,是固定的 (查找 trap table),所以可以在不同的系統都做一樣的動作
- Basic Signal Function
- kill(int pid, int sig): 其實是送 sig 的訊息給 pid
- signal(int sig, void(\*func)(int)): 其實是在做 signal handling
- Reliable Signals
- 當正在執行一個 trap 時,又有一個 trap 傳來
- 在執行 trap 時,會 lock 住其他 interrupt
- Sigmask & Sigblock: 希望這段時間不要發生 interrupt
```C
int mask;
mask = sigblock(sigmask(SIGQUIT) sigmask(SIGINT));
// 在這中間,有 SIGQUIT 或 SITINT 的 interrupt 了話,這兩種 interrupt 都會被 han 住 (存起來)
sigsetmask(mask);
// 會執行剛剛在中間被 han 住的 interrupt
```
- Sigpause
- 參考投影片 Unix P18
- 多重寫入問題 => 在某個寫入,需要先 lock 起來
- Process control
- Fork
- only copy data, text is shared
- 唯一好的產生新 process 的方式
- 幾乎是完全 copy,只有幾個不一樣的東西(連 program counter 都一樣):
- pid 不同
- ppid(parent pid) 不同(從哪裡被 fork 出來的)
- fdtable 結構一樣,但是內容位址不同,但是前三格(IO)的 address 還是一樣
- reset alarm clock
- fork() 會回傳 childpid
- 
- 這裡的 text 是 compile 出來時最下層的 read only 的 text
- share memory: 直接 fork 過去
- copy-on-write: 只有在動到資訊時,才 copy 出去(這時才把 segment 生出來)(當你 write 時,才作 copy)
- Exec
- 會繼承原來的而不會將之毀掉(?)
- ex. processA(pid=100) -fork-> processB(pid=101) -exec-> ls(pid=101)
- replace the program to the file
- loader 會在程式跑起來前,把需要預載入的東西放進去
- 真正的 system call 是 exec,其他的都是 lib (?)
- 
- Wait
- wait for child exit code
- 
- 會收到子程序的 exit code
- 如果 child exit 在 parent call wait 之前就結束了呢?
- 一旦子程序 call exit,就一定要把不用的資源環回去
- 但是有用的資源需要保留 ex. exit code
- 這時候有用的東西(像是 exit code 還會留在 stack 上)
- 直到母程序發現 -> 才會回收
- 如果 child 還沒結束,parent 就結束了(沒有回收 child 的資源)
- 這時候 child 的 ppid 就會改成 1 => 由 init 成為他的 parent

- 重點1. fork 出來的 process 的 fdtable 共用 file table => 因此不該讓兩個 process 可以同時 access file table
- 重點2. dup 出來的 file table 會是新的,只是指向 inode 的位址是一樣的 (?)
## Berkeley Socket
- Connection-Oriented Protocol

- Client - Server Arch.
- 當 machine 1(M1) 的程式(p1)要與 M2 的程式(p2)溝通時,因為無法直接得到 p2 的 pid 直接溝通,因此要有 p1 可以碰的到,架在機器上的 port 來作中間的溝通
- p1 直接打到 M2 的 port3(假設),p2 再去監控 port3 的資訊(因為 p2 是 Server End,所以其實應該說 p2 一直在監控)
- process(p2) 到 port(port3) 之間用,是用 socket 連接
- socket 會存在 fdtable 裡
- 動作
- Server
- p2 先 create 一個 socket
- 將 socket bind 到 port 上 (跟服務講要 bind 的 port)
- listen 才會真的把 bind 的東西建起來 (服務上上去)
- accept: 才開始監控 (服務才開始動)(並且 hang 住,等到 client 打他)
- Client
- p1 開啟一個 socket
- 將 socket connect 到 Server 的 port
- Server
- 在 socket 被打到之後,p2 會 create 一個新的 socket,並且用新的 socket 跟 client 連線
- 舊的 socket 繼續監聽
- 新的 socket 可以跟 client end 作 read / write / send / reseave
- Question
- 如果做完 bind 還沒作 listen,client socket 就打來
- client socket 會直接回復沒有 listen
- 如果 listen 了還沒 accept:
- client socket 會等待 accept => time out
- Connectionless Protocol

- Server: listen + accept => recvform
- Client: connect => bind
## Network
- Protocal
- 共同的規範,有點像語言
- 
- Networking
- Terms
- LAN, WAN(1)
- Repeater(2)
- Briade (3)
- Router (3)
- Gatway (3)
- Byte Order
- big endian
- small endian
- Multiplexing / Demultiplexing
- 一個系統可以用多個協定
- routing
- packet switch
- 切 packet
- ordering
- circuit switch
- **virtual circuit**
- 
- service
- connection
- sequencing
- error control
- flow control
- stream(持續傳送) vs message(封包傳送)
- full-duplex(雙向) vs half duplex(單向)
- buffer & out-of-band
- out-of-band 可以後發而先到,攔截 buffer 中的東西
- 
- send buffer
- receive buffer
- 要小心 buffer 可能會被 block 住
- routing
- static routing
- 寫死的
- 現在幾乎沒有在用了,因為通常端點不會知道另一個端點在哪裡,而是要透過中間人告知,有點像 DNS、NAT 的概念
- isolated dynamic routing
- 看到比較空的就走
- centralized / distributed dynamic routing
- routing 由中央控管 / 分層控管
- Connection / Associations
- Associations:{protocol,local-addr,local-port,foreign-addr,foreign-port}: socket 對 socket
- Half Assoc: {protocol,local-addr,local-port}: 只連到 port 的 connection
- TCP/IP family
- 
- L3
- IP -> Ethernet
- 機器 broadcase 一個 ARP ack 出來,說我要找的 MAC 與我在哪裡,被找的 MAC 如果有收到 broadcase,就會回復
- 如果 broadcase 的不是在同一個 domain 下,router 收到後,就會表示傳給我,我在把訊息傳出去
- Ethernet -> IP
- RARP (reverse)
- 先 broadcase 一個 RARP 問說我的 IP 是多少
### Client / Server
- Interactive
- Connectless Server
- 
- Connection-Oriented Servers
- 
- Concurrent, Connection-Oriented Servers
- 
- Single Process
- 