★UNP一書主要注重于 應用層 和 傳輸層之間的部分。
★包裹函數:大寫字母開頭,即封裝了出錯判斷和處理,節省了一些代碼量
★unp.h安裝步驟:
1.從網絡上下載下傳unpv13e.tar檔案,這裡用的是自己已經修改過的,可以在CentOS上運作,不需要再為一些編譯錯誤去修改。
2.安裝腳本,用于伺服器如果挂了的話重裝unp.h時友善點
tar -zxvf unpv13e.tar.gz
rm -y unpv13e.tar.gz
cd unpv13e
./configure
cd lib
make
cd ../libfree
make
cd ..
cp libunp.a /usr/lib
cp lib/unp.h /usr/include
cp config.h /usr/include
3.生成目标程式時,記得是
gcc daytimetcpcli.c -o cli -lunp
★時間擷取例程(帶注釋)
用戶端程式
#include "unp.h"
int main(int argc, char **argv){
int sockfd, n;
char recvline[MAXLINE +1 ];
struct sockaddr_in servaddr;
if (argc != 2){
err_quit("usge: a.out<IPaddress>");
}
//socket函數建立一個網際位元組流套接字
//AF_INET指網際
//SOCK_STREAM指位元組流
//sockfd是套接字的描述符
if ( (sockfd = socket(AF_INET,SOCK_STREAM, 0)) < 0){
err_sys("socket error");
}
//bzero清空socket的位址結構
//bzero是unp.h裡定義的函數,用來替代memset
bzero(&servaddr, sizeof(servaddr));
//位址族置為AF_INET
servaddr.sin_family = AF_INET;
//設定端口号為13,是時間伺服器的端口
//htons指 主機 到 網絡短整數
servaddr.sin_port = htons(13);
//inet_pton 把 argv[1]所傳遞的IP位址,轉為sin_addr的資料結構
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){
err_quit("inet_pton error for %s", argv[1]);
}
//SA就是struct sockaddr
//将本地的sockfd套接字,與servaddr中對應的伺服器進行連接配接
if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0){
err_sys("connect error");
}
//讀取傳回的内容,并将結尾置為‘\0’
//注意TCP本身不提供位元組流末尾的結束标志,即0标志。
//是以要自己置0
while ( (n = read(sockfd, recvline, MAXLINE)) > 0){
recvline[n] = 0;
fputs(recvline, stdout);
}
if (n < 0){
err_sys("read error");
}
exit(0);
}
伺服器例程:
#include "unp.h"
#include <time.h>
int main(int argc, char **argv){
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[MAXLINE];
time_t ticks;
//建立一個監聽套接字,并與13端口綁定Bind
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){
//進入睡眠,等待客戶連接配接的到達并被核心接受
//建立連接配接時,進行三次握手
//accept傳回已連接配接起來的描述符,該描述符用來與對應客戶通信
connfd = Accept(listenfd, (SA *) NULL, NULL);
printf("Get a request!");
//擷取自1970年以來的秒數
ticks = time(NULL);
//之是以用snprintf,而不是sprintf
//主要是因為該函數有緩沖區的檢查,而sprintf沒有
snprintf(buff, sizeof(buff), "%.24s\r\n",ctime(&ticks));
//發送
Write(connfd, buff, strlen(buff));
//終止連接配接,等待下一次的連接配接
Close(connfd);
}
}
★常用的一些網絡指令
檢視伺服器的網絡接口資訊(有哪些接口): netstat -i