天天看點

UNP學習筆記——第一章簡介

★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              

繼續閱讀