網路程式設計(自制伺服器)
現在的網路應用隨處可見,無法想象生活離開了網路會變得怎樣,最常見的就是通過瀏覽器上網,在位址列輸入 URL 敲擊回車,然後瀏覽器就呈現出相應的頁面。雖然現在的網路應用五花八門,但是它們都是基於相同的程式設計模型,依賴相同的程式設計介面。
每個網路應用都是基於客戶端-服務端程式設計模型的,採用這個模型,一個應用是由一個伺服器程式和一個或多個客戶端程式組成。由伺服器管理著某種資源,通過操作這些資源來為客戶端提供某種服務。需要注意的是,客戶端和服務端是程式,而不是我們常提到的機器或主機。
在系統級 I/O中已經提到過,網路也僅僅是一種檔案而已。一個插到 I/O 匯流排擴充套件槽的網路介面卡提供了網路的物理介面。從網路上接收到的資料從介面卡經過 I/O 和記憶體匯流排複製到記憶體;當然資料也同樣可以從記憶體複製到網路。
網際網路絡由大大小小的區域網和廣域網組成,這些區域網和廣域網可能採用了完全不同和不相容的技術,網際網路絡需要解決的問題是把這些不相容的網路連線起來。解決辦法就是一層執行在每臺機器和路由器上的協議軟體,這種解決方案隨處可見,比如 java 之所以誇平臺是因為不同平臺上的 JVM 做了適配。
這個協議軟體控制路由器和主機如何協同工作來實現資料傳輸,在命名上定義一種統一的主機地址格式消除差異;在資料傳輸上通過定義一種把資料位捆綁成不連續的片(包)來消除差異,一個包由包頭和有效載荷組成,包頭包括包的大小以及源主機和目的主機的地址,有效載荷包括從源主機發出的資料位。
全球 IP 因特網是最著名最成功的網際網路絡實現,每臺因特網主機都執行實現了 TCP/IP 協議的軟體。一個 IP 地址就是一個 32 位無符號整數,如下是 IP 網路程式存放的 IP 地址結構,它總是以大端法(網路位元組順序)存放。
struct in_addr {
uint32_t s_addr;
}
因特網客戶端和伺服器相互通訊使用的是 IP 地址,但是這對於人們而言太不友好了,所以因特網定義了一組更加人性化的域名,並且定義了域名集合和 IP 地址集合之間的對映。在 1988 年之前,這個對映都是通過一個叫做HOSTS.TXT
的文字檔案來手工維護的,此後改為通過 DNS(域名系統)來維護。
客戶端和服務端通過在連線
上傳送和接收位元組流來通訊,這個連線是點對點的,並且是全雙工的。一個套接字
就是連線的一個端點,每個套接字都有相應的套接字地址,由一個因特網地址和一個 16 位整數埠組成。客戶端套接字地址中的埠是核心自動隨機分配的,稱之為臨時埠;而服務端通常是很著名的埠,比如 Web 伺服器用 80 埠,電子郵件伺服器用 25 埠,並且每個知名埠都有其相應的服務名。下面是套接字地址的結構。
// _in 是 internet 的縮寫
struct scoket_in {
uint16_t sin_family; // 協議族
uint16_t sin_port; // 埠號
struct sin_addr; // IP 地址
unsigned char sin_zero[8]; // sizeof(struct sockaddr)
}
struct socketaddr {
uint16_t sa_family;
char sa_data[14];
}
核心提供了編寫網路應用所需要的函式,基本看函式名稱就知道它的功能了,下面展示了一小部分函式。
int socket(int domain, int type, int protocol);
int connect(int clientfd, const struct sockadd *addr,
socklen_t addrlen);
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
int listen(int sockfd, int backlog);
int accept(int listenfd, struct sockaddr *addr,
int *addrlen);
int getaddrinfo(const char *host, const char *service,
const struct addrinfo *hints,
struct addrinfo **result);
int getnameinfo(const struct sockaddr *sa,
socklen_t salen, char *host, size_t hostlen,
char *service, size_t servlen, int flags);
............
像用於轉換二進位制和字串表示的getaddrinfo()
、getnameinfo()
函式是可重入的。通過核心提供的這些函式就可以編寫出自己的 web 伺服器。
可重入函式主要用於多工系統中,簡單講就是可中斷函式,在這個函式執行的任何階段打斷它,作業系統去呼叫另一段程式碼,再返回控制時不會出現什麼錯誤。因為它除了使用自己棧上的變數外不依賴於任何環境。注意可重入函式不一定是執行緒安全的。
最後是原書作者自己實現的一個 TINY Wed 伺服器,用 C 實現的,在 linux 環境下編譯執行即可訪問,下圖是這個伺服器執行的效果,訪問連結http://127.0.0.1:8000/cgi-bin/adder?3&7
就可以得到運算結果。整個程式程式碼也不長,我準備好好看看再抄一遍,原始碼可訪問連結。
相關文章
- C語言+圖形程式設計——自制象棋C語言程式設計
- 程式設計師如何自制酒店 Wi-Fi?程式設計師
- 網路通訊程式設計程式設計
- py網路工具程式設計程式設計
- python 網路篇(網路程式設計)Python程式設計
- 網路程式設計-計算機網路三要素程式設計計算機網路
- python網路-Socket之TCP程式設計(26)PythonTCP程式設計
- Linux 高效能伺服器程式設計- Linux 網路程式設計基礎 APILinux伺服器程式設計API
- kestrel網路程式設計--開發redis伺服器程式設計Redis伺服器
- linux c網路網路程式設計面試題收集Linux程式設計面試題
- HUST-計算機網路實驗-socket程式設計計算機網路程式設計
- 程式設計路漫漫程式設計
- Java中神經網路Triton GPU程式設計Java神經網路GPU程式設計
- 設計卷積神經網路CNN為什麼不是程式設計?卷積神經網路CNN程式設計
- 伺服器網路程式設計之執行緒模型伺服器程式設計執行緒模型
- Web伺服器程式設計Web伺服器程式設計
- Linux 伺服器程式設計Linux伺服器程式設計
- 【go網路程式設計】-HTTP程式設計Go程式設計HTTP
- Java 網路程式設計(TCP程式設計 和 UDP程式設計)Java程式設計TCPUDP
- 網路安全程式設計 windowns防火牆培訓程式設計防火牆
- NTP伺服器(網路時鐘伺服器)助力河北交投高速網路建設伺服器
- 系統程式設計-網路-tcp客戶端伺服器程式設計模型(續)、連線斷開、獲取連線狀態場景程式設計TCP客戶端伺服器模型
- C++ 高效能伺服器網路框架設計細節C++伺服器框架
- 【Linux網路程式設計】網路程式設計常見概念Linux程式設計
- 程式設計和網路程式設計入門程式設計
- JAVA網路程式設計(2)TCP程式設計Java程式設計TCP
- 網路程式設計程式設計
- Matlab程式設計之——卷積神經網路CNN程式碼解析Matlab程式設計卷積神經網路CNN
- 程式設計師面試常問計算機網路問題程式設計師面試計算機網路
- 《Unix 網路程式設計》13:守護程式和 inetd 超級伺服器程式設計伺服器
- 網路遊戲直播原始碼自制開源版APP遊戲原始碼APP
- Python網路程式設計——程式Python程式設計
- JAVA學習線路:day14-網路程式設計Java程式設計
- Python 網路資料傳輸協議 TCP 程式設計Python協議TCP程式設計
- UDP&TCP Linux網路應用程式設計詳解UDPTCPLinux程式設計
- Java 網路程式設計 —— 非阻塞式程式設計Java程式設計
- 【網路程式設計】阻塞IO程式設計的坑程式設計
- 《Spark程式設計基礎》(Scala版)第七章簡答題答案(自制)Spark程式設計