UNP --- 第一章 介紹
阿新 • • 發佈:2019-02-09
pad fig 完成後 應用 puts 主機 定義 turn 等待
一個簡單的時間獲取客戶端程序
1 #include "unp.h" 2 3 int main(int argc, char **argv) 4 { 5 int sockfd, n; 6 char recvline[MAXLINE + 1]; 7 struct sockaddr_in servaddr; 8 9 if (argc != 2) 10 { 11 err_quit("usage: a.out <IPaddress>"); 12 } 13 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 14 { 15 err_sys("socket error"); 16 } 17 18 bzero(&servaddr, sizeof(servaddr)); 19 servaddr.sin_family = AF_INET; 20 servaddr.sin_port = htons(13); 21 if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) 22 { 23 err_quit("inet_pton error for %s", argv[1]); 24 } 25 if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0) 26 { 27 err_sys("connect error"); 28 } 29 30 while ((n = read(sockfd, recvline, MAXLINE)) > 0) 31 { 32 recvline[n] = 0; 33 if (fputs(recvline, stdout) == EOF) 34 {35 err_sys("fputs error"); 36 } 37 } 38 if (n < 0) 39 { 40 err_sys("read error"); 41 } 42 }
- socket函數創建一個網際(AF_INET)字節流(SOCK_STREAM)套接字,即TCP套接字(TCP端點)
- 需要將服務器的IP地址和端口號填入sockaddr_in結構變量中,用以指定服務器套接字相關信息。該變量的地址族為AF_INET,端口號為13(時間獲取服務器的知名端口)。
- htons用來轉換二進制端口號,inet_pton將IP地址字符串轉換為數值。
- connect函數應用於一個TCP套接字時,將與它參數中套接字指定的服務器建立TCP連接。
- 使用read循環讀取服務器的應答。因為TCP是一個沒有記錄邊界的字節流協議,所以daytime服務器的26個字節可以有多種返回方式,不能確保一次read就能完成所以讀取。當read返回0(表示對端關閉連接)或負數(表示發生錯誤)時,終止循環。
錯誤處理:包裹函數
對於每個函數調用,都必須檢查是否返回錯誤。當發生錯誤時,就使用函數輸出錯誤信息並終止程序運行。通過定義包裹函數來完成實際的函數調用,檢查返回值,並在發生錯誤時終止程序。如:
int Socket(int family, int type, int protocol) { int n; if((n = socket(family, type, protocol)) < 0) err_sys("socket error"); return n; }
一個簡單的時間獲取服務器程序
#include "unp.h" #include <time.h> int main(int argc, char* argv[]) { int listenfd, connfd; struct sockaddr_in servaddr; char buff[MAXLINE + 1]; time_t ticks; listenfd = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(13); Bind(listenfd, (SA*)&servaddr, sizeof(servaddr)); Listen(listenfd, LISTENQ); while(1) { connfd = Accept(listenfd, NULL, NULL); ticks = time(NULL); snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks)); Write(connfd, buff, strlen(buff)); Close(connfd); } }
- 調用bind函數,服務器的知名端口(13)被綁定到套接字中。IP地址為INADDR_ANY,這樣要是服務器主機有多個網絡接口,服務器進程就可以在任意網絡接口上接受客戶連接。
- 調用listen函數把套接字變為監聽套接字。
- 服務器進程在accept函數中被投入休眠,等待某個客戶的連接到達並被內核接受。TCP使用三次握手建立連接,建立完成後accept返回,返回值是已連接描述符,用於與新連接的客戶通信。
- time返回秒數,ctime將該整數值變為直觀可讀的格式。
- snprintf的第二個參數指定緩沖區的大小。
網絡拓撲相關命令
- netstat -i提供網絡接口的信息。
- netstat -r展示路由表。
- ifconfig + 接口名字,可獲得各接口的詳細信息。
- 為了找出本地網絡眾多主機IP地址,可ping本地接口的廣播地址。
UNP --- 第一章 介紹