# 網路程式設計概論, 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

- 不一定只連接特定 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)