問題:如何進行網路程式設計?
網路程式設計的本質
使用作業系統提供的介面函式,使得應用程式具備收發網路資料的能力
網路介面在程式碼層面是作業系統提供的函式
- 網路程式設計只是一系列系統函式的花式玩法
應用程式通過網路介面使用作業系統的聯網能力
- 網路程式設計是特定領域(網路)的 C 語言程式設計
協議:為進行資料通訊而預定義的資料規則
地址:網路通訊中的用於標識裝置的整數值(“xxx.xxx.xxx.xxx” 4位元組整形值可表示,單為了更容易記憶,轉換為字串)
埠號
- 裝置為收發資料而指定的數值,用於表示具體連線
- 可理解為:裝置中用於網路通訊的資料通道
- 如:一臺電腦往往只擁有一個 IP 而又有多個應用程式,此時就使用埠進行區分
角色
- 服務端:等待連線裝置
- 客戶端:發起連線的是惡被
ps : 一臺裝置可同時作為客戶端和服務端
網路知識充電站
網址就是 IP 地址嗎? URL 是什麼,域名又是什麼?
- 網址不是 IP 地址,是指網路資訊資源的地址(如:具體網頁的地址),即:URL
- 域名是 IP 地址的名別,多個域名可以指向同一個 IP 地址
- 域名 → DNS → IP 地址
協議一定是看不懂的二進位制資料嗎?
- 協議是一種約定,即:預先定義的規則
- 協議可以基於文字定義,也可以基於二進位制定義
小端系統:採用小端模式(little-endian)的系統,即:資料低位元組放在記憶體低地址中
0x12345678 int 4位元組
低地址 ? |78|56|34|12| ? 高地址
大端系統:採用大端模式(big-endian)的系統,即:資料低位元組放在記憶體高地址中
0x12345678 int 4位元組
低地址 ? |12|34|56|78| ? 高地址
網路位元組序:網址位元組順序採用大端模式,所以,在小端系統中需要做位元組轉換
網路程式設計模式
1. 準備連線
2. 連線遠端裝置
3. 收發資料
4. 關閉麗娜姐
初探網路程式設計介面
#include <sts/types.h>
#include <sys/socket.h>
函式原型 | 功能描述 |
int socket(int domain, int type, int protocal); | 建立套接字,為網路連線做準備 |
int connect(int socket, struct sockaddr *addr, socklen_t len); | 連線指定地址的遠端裝置 |
ssize_t send(int fd, const void *buf, size_t n, int flags); | 傳送資料到遠端裝置 |
ssize_t recv(int fd, void *buf, size_t n, int flags); | 接收遠端裝置發回的資料 |
int close(int fd); | 關閉連線,銷燬套接字 |
程式設計實驗:網路程式設計初體驗
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
int sock = 0;
struct sockaddr_in addr = {0};
char *tosend = "GET /index.html HTTP/1.1\nHOST: www.dt4sw.com\nUser-Agent: TEST\nConnection: close\n\n";
int len = 0;
char buf[128] = {0};
int r = 0;
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == -1) {
printf("socket error\n");
return -1;
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("47.99.217.175");
addr.sin_port = htons(80);
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
printf("connected error\n");
return -1;
}
printf("connect success\n");
len = send(sock, tosend, strlen(tosend), 0);
printf("send bytes = %d\n", len);
len = 0;
do {
int i = 0;
r = recv(sock, buf, sizeof(buf), 0);
if (r > 0) {
len += r;
}
for (i=0; i<r; ++i) {
printf("%c", buf[i]);
}
} while (r > 0);
printf("\n");
printf("recv bytes = %d\n", len);
return 0;
}
輸出:
./a.out
connect success
send bytes = 81
HTTP/1.1 200 OK
Content-Type: text/html
......
......
<script src="./static/js/app.js"></script>
</body>
</html>
recv bytes = 22382
思考:這次所編寫的網路程式是什麼角色?
答:客戶端