# 網路程式設計概論, 2020 Fall [Course Recording](https://drive.google.com/drive/folders/1PFybejsLmD13NnIQFqDss3MOEtKY0WSd?usp=sharing) [Homework & Exam code](https://github.com/FadaSlore/Intro.ToNP) # Basic Concepts ## TCP/IP Reminder - IP:network layer protocol(host $\leftrightarrow$ host) - 不同 hosts 間如何交換資訊 - UDP/TCP:transport layer protocol(process $\leftrightarrow$ process) - 不同 hosts 的 processes 間如何交換資訊 - UDP:unrelibale - 不保證送出資訊的順序與送達 - TCP:reliable, byte-stream - 預先建立連接:connected channel,而後開始交換資訊 - FIFO,雙向 ### IP(Internet Protocol) - Packet oriented - 在任兩個 hosts 間傳遞 - unreliable ### UDP(User Datagram Protocol) - Packet oriented - 將要傳送的訊息切割成 datagrams(packets),分別傳送 - 優缺點 - 優:fast - 缺:unreliable(交給應用處理) - out of order - lost - duplicate - Local LAN 下,發生上述情況機率較小 ### TCP(Transmission Control Protocol) - **Connection oriented、reliable byte-stream** - full duplex 雙向,單一時間可以雙向資料傳輸 - 保證封包的順序與可達 - 需要額外訊息(control message)以保證所求 - 若封包遺失 $\rightarrow$ 重傳 - 需要有 buffer - 若 out of order,需要先存入 buffer ### Application Protocols - Standard application protocols - initial setup(本機預先配置) - 定義公開,可自行根據定義實作 - Nonstandard application protocols - 另外(自行)下載 ## Model ### The Client Server Model - **Request/Response message** - Server - 服務提供者 - 等待 request 到達(被動) - 針對 request 產生並送出 response - 可能同時對不同的 clients 提供服務 - Client - 產生並送出 request 給 server - 等待 response - Application protocol 定義 request/response information ### The Peer to Peer Model(P2P) - 共同合作 - 不分 client/server - 都會收/發 request/response - 相同 capablilties & responsibilities ### Email Application - Client$_A$ $\rightarrow$ Server $\leftarrow$ & $\rightarrow$ Client$_B$ - 可能中間會經過多個 servers - server network: server - server ### Three Tier Client Server Model - Multiple Tier Client Server Model - Client $\leftrightarrow$ Application Server $\leftrightarrow$ Database Server - 一個 Application Server 可能有多個 Clients 連接 - 一個 Database Server 可能有多個 Application Servers 連接 - Application Servers 是 Database Server 的 client ### Hybrid of Client/Server and P2P - 現今大部分的 application 都是這種 - Central Servers(檔案/內容持有者) - 使用者/檔案(內容)狀態 - client/server - 傳送資料 - P2P ## Clients and Servers - Client(發起 communication) - 發出 request - 調用 client software 以使用網路服務 - Server(等待 clients 送來的 requests) - 處理 request,產生 response並回傳給傳送該 request 的 client ### Privileges and Complexity of Servers - 考慮系統資源 - Server 需要考慮 - Authentication - Authorization - Privacy - Protection ### Classifications #### Client - Standard vs. Nonstandard - 看對應的 application - Fully parameterized - destination machine + destination protocol port number #### Server - Connectionless vs. Connection-Oriented - UDP:Conntionless - TCP:Connection-Oriented - Stateless vs. Stateful - Stateless: - 每一個收到的 request 對 server 來說都是彼此獨立的 - State Information: - 進行中互動的狀態資訊(Ex. 已開啟檔案…) - 由 server 維護 ##### Ex. File Server ###### Stateless - 允許遠端 client 存取 files - client 的 requests 需要包含完整資訊 - Ex. account、access file、read/write bytes… ###### Stateful - Server 維護 open file table - table 中儲存已連接的 client 與其正在存取的 files 資訊 - request 訊息不需要有全部資訊 - 對於已開啟的 file:table index(entry)、size… ##### Other Issues for Stateful Servers - 辨別 client - 網路端點(IP & port number) - Handles(抽象的資料型態) - Staelessness:protocol issue - applicaton protocol - 若訊息與過去訊息相關,則無法提供 stateless 互動 - 但若該 application protocol 被設計為使操作有冪等性,則 server 可為 stateless #### Servers as a Client - 當 server 產生 response 的過程中需要存取其他網路服務 - 該 server 會對其他網路服務的 server 發送 request - 即,該 server 會作為 client 存在 #### A service provided by multiple servers - Service 由多個 servers 一起提供 - server 與 server 之間互通 - client 可以連接到不同 server(提供的服務相同) #### An agent represents multiple servers - Proxy server - Client $\overset{proxy\ server}{\rightarrow}$ Web server ### Concurrency #### In Servers - 同時處理多個進入的 requests(來自不同的 clients) - 提供好的 response time #### In Clients - 根據 functionality 分為可獨立存在並執行的 components - 一個 client 同時連線多個 servers - 得到快速回覆 - 結合 responses - 動態需求 # Inter-Process Communications ## Cooperating Processes - Independent process - 彼此獨立,執行中不會互相影響 - Cooperating processes - 彼此會互相影響 - IPC (inter-process communication) model - Shared memory - 同一個 host 的 processes - Message passing - 相同/不同 hosts 的 processes ## Purposes for IPC - Data Transfer - Sharing Data - Event notification - Resource Sharing and Synchronization - Process Control ### Shared memory - 不同 processes 之間: - Private address space - Shared memory - 不需要做資料複製的動作(直接 read/write) - Q:資料是否同步到最新?(等待 writer 完成再 read) - 同一個 process 內不同的 threads - Shared address space-heap:共享資料 - 優缺點 - 優點 - 快速、簡單 - 缺點 - 資料同步 - 避免 race condition ### Message passing - processes 需要用到時,經由 kernel 讀取別的 processes memory 再寫入 - 資料傳送:sender (source) & receiver (destination) - Ex. pipes, sockets - 優缺點 - 優點 - 程式可讀性 - 改善模組化 - 缺點 - 複製訊息(額外負擔) - Issues: - 如何定義(name) source & destination - sender 等待 receiver? - Blocking & Non-blocking(需要 buffer) #### Unicast v.ss Multicast - unicast: 一對一 - multicast: 一對多 ##### Ex. Message Passing in basic HTTP - Operations(HTTP request & response) - C1:make connection - S1:accept connection - C2:send request - S2:receive request - S3:send response - C3:receive response - C4:disconnect - S4:disconnect #### Synchronization in Message Passing - blocking(synchronous) - sender:直到訊息已傳送 - receiver:直到訊息可被存取 - non-blocking(asynchronous) - sender:送出,然後直接 return(不考慮 receiver 有沒有收到) - 需要 buffer - receiver:有效訊息/null(若沒有等待中的可收訊息-直接 return,不會等待) ##### Case 1. Non-Blocking Send & Blocking Receive - sender: - acknowledgment - 知道 receiver 是否有收到 - receiver:等待資料 - 資料未到 $\rightarrow$ blocking - 若 sender 傳送不成功,則可能會無限期等待 - 設定 timeout ##### Case 2. Blocking Send & Blocking Receive - send & receiver: - 當溝通連接為 un-buffered(沒有訊息列) - tight synchronization(rendezvous) - 兩個 activities 在該處交會 ##### Case 3. Blocking Send & Non-Blocking Receive - 可能場景 - receiver 執行 receive op - sender 傳送後 - sender 傳送前 - 資料到達有通知(interrupt) - receiver 被通知後告知sender 已收到 - 資料到達無通知 - sender 有可能會出現無限期等待 ##### Case 4. Non-Blocking Send & Non-Blocking Receive - buffer - 有通知 - 無通知 $\rightarrow$ 定期檢查(timer) #### Naming in Message Passing - Direct channel - process ID - 有時候可能無法知道 - Indirect channel - shared mailbox/queue - sender & receiver 都知道 ##### Direct Channel - 定義方式 - Symmetric Addressing - sender & recevier 都要指明對方 - Asymmetric Addressing - sender 指明 - receiver 指明 id set - 送 ack 給 sender - 特性 - 兩個 processes 之間自動產生 link - 且在每對間只會有一個 link - processes 至少有一方要先知道對方 - 缺點 - 必須要知道對方的 name/ID ##### Indirect Channel - 訊息透過 maileboxes/ports 收/送 - 每一個 mailbox 都有唯一的 ID - 只有當 processes 共享一個 mailbox 時才可以互相溝通 - 特性 - 只有當 processes 共享相同的 mailbox 時才會建立 link - 單一 link 可能與多個 processes 相關 - 兩個 processes 間可能有多個 links - 操作 - 產生新的 mailbox - send/receive 對象:mailbox - 刪除 mailbox #### Message Buffering - 實作 - Zero-capacity - 一定要兩邊同時存在(sync) - blocking send & blocking receive - $\rightarrow$ **rendezvous** - Bounded capacity - 固定大小的 buffer - full:sender 會被 block - empty:receiver 會被 block - Unbounded capacity - ideal case ## Message Passing IPCs - Pipe - FIFO(named pipe) - Socket ### Pipes - 單向 reliable channel - 分為 write / read 端 - FIFO - 多用於單個 process 中的兩個 threads/parent-child - 有限容量 - full:writer 會 block 直到有空 - empty:reader 會 block 直到有資料可用 - 自動同步相關的 processes #### Creating pipes in Linux - `pipe` system call - return:大小為 2 的整數陣列(file descriptors) - 0:read - 1:write #### Example ```c= #include <unistd.h> #include <fcntl.h> #include <stdio.h> char *message = "This is a message!!!"; main() { char buf[1024]; int fd[2]; pipe(fd); /* create pipe */ if (fork() != 0) { /* I am the parent */ write(fd[1], message, strlen(message)+1); } else { /* Child code */ read(fd[0], buf, 1024); printf("Got this form Parent process!!: %s\n", buf); } } ``` ### FIFOs - first-in, first-out - 也稱作 named pipes - 任何 process 都可以開啟/關閉 FIFO(shared mailbox) - FIFO 的兩端不需要有關聯性 #### Create FIFOs in Linux - `mkfifo` ```shell= % mkfifo /tmp/fifo ``` - system calls - `open`、`read`、`write`、`close` - 讀寫預設為 block #### Working with FIFO in a Shell - Create a FIFO - `mkfifo fifo` - `mknod fifo p` - 讀寫 從/到 FIFO - 開啟兩個 terminals ### Socket - **雙向**收送資料 - 代表 channel 的某一端點 - Named:IP address+port number - Communication 由一對 sockets 組成 #### Socket Concepts - 產生 socket 所需參數: 1. communication style 2. namespace 3. protocol - 有可能出現無法支持的組合 - Communication Style - 切割成 packets 傳送 - Connection styles - 保證傳送順序正確(connection-oriented) - Datagram styles ##### Namespace - 定義 socket addresses(辨別 socket 連接端點之一)如何敘寫 - local namespace - ordinary filenames - Internet namespace - host 的 IP address+port number - port number:辨認同個 host 上不同的 sockets ##### Socket Protocols - 定義資料如何傳送 - 常使用的協定 - TCP/IP - AppleTalk network protocol - UNIX local communication protocol # Socket API - What is an API? - Application Programming Interface. - What is a Socket? - 抽象化的結果 - 資料可以 傳至/收自 在 相同/不同機器 上執行的 process ## The Socket API - 連接端點 - IP Address+Port Number - UNIX file descriptors - 網路 Sockets 類型: - SOCK_STREAM(TCP) - Connection-oriented - Reliable - SOCK_DGRAM(UDP) - Connectionless - Unreliable ## Network Byte Order Conversions - Network byte:big-endian byte order - `htons()`:Host to Network Short - `htonl()`:Host to Network Long - `ntohs()`:Network to Host Short - `ntohl()`:Network to Host Long - `inet_addr()`:轉換十進位 IP address 到 網路位元序的unsigned long :thinking_face: 9/28 10:10 ## Socket Functions [<sys/socket.h>](https://pubs.opengroup.org/onlinepubs/007908799/xns/syssocket.h.html) ```c= #include<sys/socket.h> ``` - `socket`:建立 socket - `bind`:連結 socket 到本機的 IP address & port number - `connect`:與遠端 host 連接(setup connection) - `listen`:等待連接(由 server 使用) - `accept`:接受新連接&取得新的 socket(用於後續的資料傳送) - `send` and `recv`:經由連接傳/收資料 - `read` and `write`:經由連接傳/收資料 - `sendto` and `recvfrom`: ```c= int sendto(int sockfd, const void *msg, int len, int flags, ocnst strut sockaddr *to, int tolen); int recvfrom(int sockfd, void *buf, int len, int flags, struct sockaddr *from, int *fromlen); ``` - `close` and `shutdown` - shutdown - 斷掉 Two way channel 中的其中一端 - server 處理 request 需要時間 $\rightarrow$ 先關掉 client 的 send 端 - `getpeername` ```c= getperrname(int sockfd, struct sockaddr *addr, socklen_t *addrlen); ``` - `gethostbyname` - 回傳 IP address of a computer ```c= gethostbyname(const char *name); ``` - `getservbyname` - 回傳 port number ```c= getservbyname(const char *name, const char *proto); ``` - `getprotobyname` - 回傳 portocol number ```c= getprotobyname(const char *name); ``` - `getaddrinfo` - 取得 server 的 IP address 和 port number ```c= getaddrinfo(void *hostname, void *servicename, struct addrinfor *hints, struct addrinfor **result); ``` ### The connect function call ```c= int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen); ``` - TCP - client 使用 - 建立與 server 的連接 - UDP - 不會有真正的 connection - virtual connection - 不需要指定 address(因為已存) - client 使用 - 紀錄 server IP & port - 後續使用不需再給 remote server 的 address - 失敗 - server queue full - 無法儲存 request ### The bind function call ```c= int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen); // return 0 if OK, -1 on error ``` ### The listen function call ```c= int listen(int sockfd, int backlog); ``` - 過渡 - TCP socket:未連接$\rightarrow$被動 ### The accpet function call ```c= int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen); // return nonegative descriptor if OK, -1 on error ``` - TCP server 使用 - accept 成功:回傳新的 socket descriptor - 等待序列中的連接要求 - 後續傳送資料時,使用回傳的 socket descriptor - origin socket descriptor: 僅用於 accept - 失敗 - descriptor table full(沒有 free entry 可用) - system buffer full - 沒有 連接要求: blocking ## Data Structure ### hostent ```c= struct hostent { char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype; /* host address type */ int h_length; /* length of address */ char **h_addr_list; /* list of addresses */ } ``` ### addrinfo ```c= struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; struct sockaddr *ai_addr; char *ai_canonname; struct addrinfo *ai_next; } ``` # The Client Software Examples ## The UDP Client Algorithm - 找到要連接的 server 的相關 address - `gethostbyname`+`getservbyname`+`getprotobyname` or - `getaddrinfo` - 分配 socket - `socket(AF_INET, SOCK_DGRAM, 0)` - UDP 自由選擇沒有被使用的 port - socket 用來跟特定的 server 連接(僅連接一個 server) - `connnect` and - 傳輸:`send`+`recv` / `write`+`read` - 若 UDP socket 需要與多個 servers 連接 - `sendto` and `recvfrom` - 釋放 socket - `close` / `shutdown` ### The UDP Client Server Paradigm Unconnected Mode ![](https://i.imgur.com/lTVOYjh.gif) - 不一定只連接特定 server - Client:`getaddr-echo-client.txt` - Server:`un-echo-server.txt` - 也可以使用 `gethostbyname`:`gethost-echo-client.txt` ### The UDP Client Server Paradigm Pseudo Connection Mode | Client | | Server | | --------------- | ------ | ------------- | | `socket` | | `socket` | | `getaddrinfo` | | `getaddrinfo` | | `connect` | -----> | `bind` | | `write`/`send` | ——> | `recvfrom` | | `read`/`recv` | <—— | `sendto` | - Client:`udp-time-client.txt` - Server:`udp-time-server.txt` ## The TCP Client Algorithm - 找到要連接的 server 的相關 address - `gethostbyname`+`getservbyname`+`getprotobyname` or - `getaddrinfo` - 分配 socket - `socket(AF_INET, SOCK_STREAM, 0)` - TCP 自由選擇沒有被使用的 port - socket 用來連接 remote server - `connnect` and - 傳輸:`send`+`recv` / `write`+`read` - 釋放 socket - `close` / `shutdown` ### The TCP Client Server Paradigm | Client | | Server | | --------------- | -------------------------------------------- | ---------- | | `socket` | | `socket` | | | | `bind` | | | | `listen` | | `connect` | $\overset{Connection\ request}{\rightarrow}$ | `accept` | | `write`/`send` | $\overset{Data\ message}{\rightarrow}$ | `recvfrom` | | `read`/`recv` | $\overset{Data\ message}{\leftarrow}$ | `sendto` | - Client:`tcp-echo-client.txt` - Server:`tcp-echo-server.txt` ## Some Important Facts - UDP socket - `recvfrom`: 整段訊息 - TCP socket - `read` / `recv`: 特定 bytes # The Server Software Alogrithm ## The Server Software Architecture - Iterative vs. Concurrent - iterative - concurrent - 可以同時處理多個 reuqests - Connectionless vs. Connection-oriented Access - TCP: connection-oriented - UDP: connectionless ### Iterative Server Algorithm - Iterative connectionless servers (Iterative UDP servers) - Receive Message $\rightarrow$ Process Message $\rightarrow$ Send Response - Iterative connection-oriented servers (Iterative TCP servers) - Accept Connection $\rightarrow$ - \{Receive Message $\rightarrow$ Process Message $\rightarrow$ Send Response\}\* - $\rightarrow$ Close Connection #### Ex. un-echo-server ### Iterative TCP Server - Create - socket(connection / master) - Bind - master socket $\rightarrow$ passive mode - Accept - Repeat: - Read - Process - Send - Finish ## Concurrent Server Algorithm - Concurrent connectionless servers (Concurrent UDP servers) - Conncurrent connection-oriented servers (Concurrent TCP servers) ### A Concurrent UDP Server Template - Master Process (Thread) - Create - Bind - Repeatdly call `recvfrom`: 收下一個 request - create new slave process (thread): 處理 request - 收到的訊息 & sender 位址 $\rightarrow$ slave process - Slave Process - 處理 request - 產生 response - 拿到 requesting client 的位置(IP, Port) - `sendto`: 送出 response - Exit # POSIX Multi-Thread Programming ## Single & Multi-Threaded Processes ## The Producer Consumer Problem ### Example - PC-CV.c ```c= #include <pthread.h> #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <time.h> #include <string.h> int sum, total; void *producer(int producer_id); void *consumer(int consumer_id); #define BUFFER_SIZE 5 #define PRODUCER_NUM 3 #define CONSUMER_NUM 2 typedef struct{ int prod_id; // producer id int value; // produced item value } item; struct { pthread_mutex_t mutex; pthread_cond_t notbusy; // there exists free buffer pthread_cond_t notempty; // there exists free item int top; item buffer[BUFFER_SIZE]; } shared_stack; main(int argc, char *argv[]) { int i; pthread_t tid; pthread_attr_t attr; (void) pthread_attr_init(&attr); (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); (void) pthread_mutex_init(&shared_stack.mutex, NULL); (void) pthread_cond_init(&shared_stack.notbusy, NULL); (void) pthread_cond_init(&shared_stack.notempty, NULL); shared_stack.top = -1; // empty stack } ``` ## The Shared Stack in a MT Process - 一定至少要有一個 lock 以保護 shared stack # POSIX MP Synchronization ## Process Synchronizations - Shared data(memory) segament ## Semaphore - 與 mutex 差別: - mutex 為 0、1 變數 - semaphore:允許最多 N 個 process 同時存取共享資料 - include ```c= #include <semaphore.h> ``` ### The semaphore functions #### `sem_init()` ```c= int sem_init(sem_t *sem, int pshared, unsigned int value); ``` - `sem_init()` - 定義 semaphore 值 - `pshared` - 0: - 非 0:用於在同一個 host 上,擁有 shared memory 的 processes 之間 - `sem_post()` - `sem_wait()` ### The semaphore operations ```c= int sem_wait(sem_t *sem); ``` - 減少(lock) ```c= int sem_post(sem_t *sem); ``` - 增加(unlock) ## The Shared Memory Creation - ```c= #include <sys/mman.h> // must be linked with -lrt option int shm_open(const char *name, int flag, mode_t mode); // reutrn a new file descriptor (referring to the POSIX shared memory) if success int shm_unlink(const char *name); ``` - name - flag - mode - 可被執行的狀況 ## `ftruncate`&`mmap` - `ftruncate()` ```c= #include <unistd.h> #include <sys/types.h> int ftruncate(int fd, off_t length); ``` - `mmap()` ```c= #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offest); // returns a pointer (address pointer to the mapped area) if success ``` - `addr`:若為 `NULL`,則 kernel 選擇新增 mapping 的地址 - `prot`:保護模式 `PROT_READ | PROT_WRITE` - `flags`:`MAP_SHARED` ## The MP Producer Consumer Solution ```c= typedef struct { int prod_it; //producer id int value; // the item value } item_t; typedef struct { sem_t mutex; int top; item_t buffer[BUFFER_SIZE]; }stack_t; stack_t *shm_addr; ``` # Introduction to NP - Homework ## Code Reference - [Chat_NP](https://github.com/danilromas/Chat_NP) - [NetworkProgramming](https://github.com/Dada870423/NetworkProgramming) ## Homework 1 ### Question - socket - [reference1](https://docs.python.org/3/library/socket.html) - [reference2](https://clay-atlas.com/blog/2019/10/15/python-chinese-tutorial-socket-tcp-ip/) - random number - multi-clients in TCP - [reference1](https://stackoverflow.com/questions/26445331/how-can-i-have-multiple-clients-on-a-tcp-python-chat-server) - [reference2](https://codezup.com/socket-server-with-multiple-clients-model-multithreading-python/) - \_thread vs. threading - [reference1](https://www.runoob.com/python3/python3-multithreading.html) - TCP and UDP simultaneously - `select` - [reference1](https://www.geeksforgeeks.org/tcp-and-udp-server-using-select/) ## Homework 2 ### Question - socketserver - [reference1](https://docs.python.org/3/library/socketserver.html) - multiprocessing with shared memory - [reference1](https://docs.python.org/3/library/multiprocessing.shared_memory.html) - multithreading in TCP - [reference1](https://www.techbeamers.com/python-tutorial-write-multithreaded-python-server/) - multithreading - [reference1](https://www.1ju.org/python/python-multithreading) ## Homework 3 - [Chatroom sequence diagram](https://hackmd.io/@9S8mQBvrRhCNyxRteejhFA/SksL62RtP) - 討論區 - 自己的版面上不會再輸出一次自己發出的訊息 - 只會有訊息,不會有 `Name[time]:` - chatroom owner `detach` - 對在同一個 chatroom 的其他人來說沒有變化 - chatroom 需要至少 5 個 connection - user 只會在一邊 login - 相同 port - user A 登入後創建聊天室,執行 leave-chatroom(聊天室已關閉),登出後 login user B,B 可以在 `create-chatroom` 使用與 A 相同的 port - `create-chatroom` - server 建完後直接進入 chatroom - chatroom server 的 IP address - 從 bbs server 獲得 chatroom owner 的 IP address - chatroom 聊天紀錄 - `leave-chatroom` 後,聊天紀錄會保留在 client(chatroom owner)端 - `restart-chatroom` 會得到最近的三條訊息 - 不同 client 端 `restart-chatroom` - 若環境為 localhost 可以 - 否則不行,因為 host IP 不同 - `logout` 前 `exit` - 測資不會有這樣的情況 - 同一個 user 只能開一個 chatroom - `detach` in chatroom - chatroom owner:當成 command - other client(s):當成對話訊息 - `join-chatroom` - 不會加自己的 chatroom - Chatroom - [reference1](https://www.geeksforgeeks.org/simple-chat-room-using-python/) - p2p chat - [reference1](https://github.com/grakshith/p2p-chat-python) - Time - [reference1](https://www.programiz.com/python-programming/datetime/current-time) - `detach` 後的沒有變化是指要繼續 handle 其他 clients 的 connection? - mulitprocessing - [reference1](https://docs.python.org/3/library/multiprocessing.html) - nonblock input - `select.select( [sys.stdin], [], [], Timeout)` - [reference1](https://techdevops.wordpress.com/2015/03/24/non-blocking-io-keyboard-listener-in-python/) # NP_Exam ## 1st Exam - get file - [Working With Files in Python](https://realpython.com/working-with-files-in-python/) - [pathlib](https://docs.python.org/3/library/pathlib.html) - [os](https://docs.python.org/3/library/os.html)