1. 程式人生 > 實用技巧 >網路程式設計核心考點

網路程式設計核心考點

網路程式設計核心考點

第一章

1. 分層

  • 主機-網路層:負責物理層和網路層的資料轉換
  • 互連網路層:網路之間的資料傳輸
    • IP協議:盡力而為、不可靠、無連線
  • 傳輸層:程序之間的端到端資料傳輸
  • 應用層

2. TCP工作流程

  • 建立連線-傳輸資料-斷開連線
  • 狀態之間的轉換,三次握手,四次揮手。
  • TIME_WAIT存在的兩個理由就是:
    • 可靠地實現TCP全雙工連線的終止;
    • 允許老的重複分節(資料報)在網路中消逝。

3. 伺服器的分類

  • 按照使用的傳輸協議不同可以分為無連線的伺服器與面向連線的伺服器;
  • 按照是否維護與客戶互動活動的資訊可以分為有狀態伺服器與無狀態伺服器;
  • 按照處理與客戶互動的機制不同又可以分為迴圈伺服器與併發伺服器。

4. 位元組序

  • 主機位元組序:小尾位元組序(小存小)
  • 網路位元組序:大尾位元組序(小存大)

5. 套接字型別

  • 流式套接字:SOCK_STREAM、TCP
  • 資料報式套接字:SOCK_DGRAM、UDP
  • 原始套接字:SOCK_RAW

6. 重點函式

  • 位元組序之間的轉換:htonl()、htons()、ntohl()和ntohs()
  • 清空函式:memset()清空一個結構型別的變數或陣列
    • int buf[50];
    • memset(buf, 0, 50*sizeof(int))
  • strcmp()函式:比較兩個字串的大小
  • atoi()函式:字串轉換成整型數值

7. 特殊埠

  • FTP:21
  • HTTP:80
  • POP3:110
  • SMTP:25
  • DNS:53
  • TFTP:69
  • SNMP:161

第二章

1. 函式

  • socket(int domain,int type,int protocol)
    • (協議組,套接字型別,協議號)
    • TCP:socket(PF_INET,SOCK_STREAM,0)
    • UDP:socket(AF_INET,SOCKET_DGRAM,0)
  • connect(int sockfd,struct sockaddr* serv_addr,int addrlen)
    • (套接字描述符,伺服器地址指標,地址長度大小)
    • connect(csock,(struct socketaddr*)&servaddr,sizeof(struct sockaddr))
  • bind(int sockfd,struct sockaddr *my_addr,int addrlen)
    • (套接字描述符,本機的地址,地址長度大小)
    • bind(ssock,(struct sockadr*)&servaddr,sizeof(strucr sockaddr))
  • listen(int sockfd,int backlog)
    • (套接字描述符,佇列大小)
    • listen(ssock,10)
  • accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
    • (套接字描述符,客戶機地址,地址長度大小)
    • accpet(ssock,(struct sokaddr*)&clientaddr,sizeof(struct sockaddr))
  • send(int s, const void *buf, size_t len, int flags)
    • (套接字描述符,要傳送的資料,資料長度,方式)
    • send(sock,buffer,strlen(buffer),0)
  • recv(int s, void *buf, int len, unsigned int flags)
    • (套接字描述符,存放接收資料的緩衝區,資料長度,方式)
    • recv(sock,buffer,strlen(buffer),0)
  • sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen)
    • (套接字描述符,要傳送的資料,方式,資料長度,主機地址,地址長度大小)
    • send(sock,buffer,strlen(buffer),(struct sockaddr*)&addr,siezof(struct sockaddr))
  • recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen)
    • (套接字描述符,存放接收資料的緩衝區,資料長度,方式,主機地址,地址長度)
    • recvfrom(sock,buffer,strlen(buffer),0,(struct sockaddr*)&addr,seizof(struct sockaddr))

2. 流程加函式

TCP伺服器設計流程

  • 呼叫socket()函式建立伺服器套接字
    • TCP:int ssock=socket(PF_INET,SOCK_STREAM,0)
  • 呼叫bind()函式繫結本地端點地址
    • bind(ssock,(struct sockaddr*)&servaddr,sizeof(struct sockaddr) “這裡可以寫成(sizeof(servaddr)” )
  • 呼叫listen()將套接字設為被動模式,並設定等待佇列長度
    • listen(ssock,10)
  • 呼叫accept()函式等待連線
    • accept(ssock,(struct sockaddr*)&clientaddr,sizeof(clientaddr))
  • 呼叫recv()函式接收資料
    • recv(ssock,buffer,strlen(buffer),0)
  • 呼叫send()函式傳送資料
    • send(ssock,buffer,strlen(buffer),0)
  • 呼叫close()函式關閉套接字
    • close(ssock)

TCP客戶端設計流程

  • 呼叫socket()函式建立伺服器套接字
    • TCP:int csock=socket(PF_INET,SOCK_STREAM,0)
  • 呼叫connect()函式連線伺服器
    • connect(csock,(struct sockaddr*)&servaddr,sizeof(servaddr))
  • 呼叫recv()函式接收資料
    • recv(csock,buffer,strlen(buffer),0)
  • 呼叫send()函式傳送資料
    • send(csock,buffer,strlen(buffer),0)
  • 呼叫close()函式關閉套接字
    • close(csock)

UDP伺服器設計流程

  • 呼叫socket()函式建立伺服器套接字
    • UDP:int ssock=socket(AF_INET,SOCKET_DGRAM,0)
  • 呼叫bind()函式繫結本地端點地址
    • bind(ssock,(struct sockaddr*)&servaddr,sizeof(struct sockaddr))
  • 呼叫recvfrom()函式接收資料
    • recvfrom(ssock,buffer,strlen(buffer),0,(struct sockaddr*)&clientaddr,sizeof(clientaddr))
  • 呼叫sendto()函式傳送資料
    • sendto(ssock,buffer,strlen(buffer),0,(struct sockaddr*)&clientaddr,sizeof(clientaddr))
  • 呼叫close()函式關閉套接字
    • close(ssock)

UDP客戶端設計流程

  • 呼叫socket()函式建立伺服器套接字
    • UDP:int csock=socket(AF_INET,SOCKET_DGRAM,0)
  • 呼叫recvfrom()函式接收資料
    • recvfrom(csock,buffer,strlen(buffer),0,(struct sockaddr*)&servaddr,sizeof(servaddr))
  • 呼叫sendto()函式傳送資料
    • sendto(csock,buffer,strlen(buffer),0,(struct sockaddr*)&servaddr,sizeof(servaddr))
  • 呼叫close()函式關閉套接字
    • close(csock)

3. Windows下的套接字程式設計

Windows下的套接字程式設計流程與Linux是相似的

  • 使用WSAStartup()函式初始化WinsockDLL
  • 關閉套接字函式改為closesocket()
  • 最後呼叫WSACleanup()函式接數Winsock Socket API

第三章

1. 設計流程加函式

TCP伺服器設計流程

/**
*詳細介紹和單次伺服器相同
*客戶端設計與單次相同(整體放進迴圈體並設計結束條件)
*/
socket(...);
bind(...);
listen(...);
while(1)
{
 accept() (...);
 process(...);
 close(...);
}
close(...);

UDP伺服器設計流程

/**
*詳細介紹和單次伺服器相同
*客戶端設計與單次相同(整體放進迴圈體並設計結束條件)
*/
socket(...);
bind(...);
while(1)
{
 recvfrom(...);
 process(...); 
 sendto(...);
}
close(…);

第四章

1. 差別

  • 迴圈伺服器是指伺服器在同一時刻只可以響應一個客戶端的請求的伺服器
    • 設計、程式設計、除錯和修改簡單的優點
    • 使用者對時間要求低
  • 併發伺服器就是指在同一個時刻可以處理來自多個客戶端的請求的伺服器
    • 各個請求所需要的處理時間差別非常大
    • 在一臺多處理器的計算機上執行

2. 程序、執行緒各自的優缺點

  • 程序優點:程式設計、除錯簡單,可靠性較高。
  • 程序缺點:建立、銷燬、切換速度慢,記憶體、資源佔用大。
  • 執行緒優點:建立、銷燬、切換速度快,記憶體、資源佔用小。
  • 執行緒缺點:程式設計、除錯複雜,可靠性較差。
  • 程序只是資源分配的單位,而真正可以在處理器(CPU)上獨立排程執行的基本單位是執行緒。

3. 重點函式及使用

fork()函式:建立一個新程序

  • 若fork()函式呼叫成功,則在子程序中其返回值為0,而在父程序中其返回值為子程序的程序號(程序ID)

  • 若fork()函式呼叫不成功,則在父程序中其返回值為-1

     /**
     *兩種方式
     */
     int pid;
     pid = fork();  //呼叫fork()函式建立一個新程序
     if(pid == -1 ) 
     {  //若呼叫fork()函數出錯
      perror ("fork failed!"); 
      exit(1);
     } 
     else if( pid = =0 ) 
     {  //以下是子程序所執行的操作
      printf("This is the child process!"); 
     } else 
     {  //以下是父程序所執行的操作
      printf("This is the parent process!"); 
     }
    
     int pid;
     pid=fork();
     switch (pid) {
     case -1: //若呼叫fork()函數出錯
     perror("fork failed!");
     exit(1); 
     case 0: //以下是子程序所執行的操作
     printf("This is the child process!");
     break;
     default: //以下是父程序所執行的操作
     printf("This is the parent process!");
     break;
     }
    
  • getpid()函式:獲得當前程序的程序號

  • getppid()函式:獲得當前程序的父程序的程序號

  • wait()函式:程序一旦呼叫了wait()函式,就立即阻塞自己

    • WIFEXITED:等待子程序如果結束返回非0值
    • WEXITSTATUS:等待子程序結返回子程序由exit()返回的結束程式碼
    • WIFSIGNALED:等待子程序如果訊號結束返回非0值
    • WTERMSIG:若子程序因為訊號結束則利用該巨集可獲得子程序的中止訊號程式碼
    • WIFSTOPPEN:子程序處於暫停執行狀態則該巨集將返回非0值
    • WSTOPSIG:若子程序處於暫停狀態則利用該巨集可獲得引發子程序暫停的訊號程式碼
  • waitpid()函式:pid_t waitpid(pid_t pid, int *status, int options)

    • pid:
      • pid>0時,只等待程序ID等於pid的子程序,不管其它已經有多少子程序執行結束退出了,只要指定的子程序還沒有結束,waitpid()就會一直等下去。
      • pid=-1時,等待任何一個子程序退出,沒有任何限制,此時waitpid()和wait()的作用完全等同。
      • pid=0時,等待同一個程序組中的任何子程序,如果子程序已經加入了別的程序組,waitpid()不會對它做任何理睬。
      • pid<-1時,等待一個指定程序組中的任何子程序,這個程序組的ID等於pid的絕對值。
        -status:用來儲存被收集程序退出時的一些狀態,是一個指向int型別的指標
    • options:
      • options置為WUNTRACED,則當子程序處於暫停狀態,waitpid()將馬上返回;
      • options置為WNOHANG,則即使沒有子程序退出,waitpid()也將立即返回;
      • options置為0,則waitpid()會像wait()那樣阻塞父程序,直到所等待的子程序退出
    • signal()函式用法:signal(SIGALRM, handler),handler是預先定義好的函式
    • pthread_create():建立執行緒函式
    • pthread_exit():終止執行緒
    • pthread_attr_init():初始化結構體
    • pthread_attr_destroy():刪除
    • pthread_attr_setdetachstate()、pthread_attr_getdetachstate():設定、獲取執行緒的分離狀態
    • pthread_attr_setinheritsched()、pthread_attr_getinheritsched():設定、獲取執行緒的繼承性

4. 避免產生殭屍程序

  • 父程序可通過呼叫wait()或waitpid()等函式來等待子程序結束,從而避免產生殭屍程序,但這會導致父程序被掛起(即父程序被阻塞,處於等待狀態)
  • 呼叫signal()函式為SIGCHLD訊號安裝handler來避免產生殭屍程序
  • 呼叫signal(SIGCHLD, SIG_IGN)函式來通知核心在子程序結束後將會被核心自動回收

第五章(個人認為考點不多,後面沒有整理)

1. 三種互斥鎖

  • 快速互斥鎖是指呼叫執行緒會阻塞直至擁有互斥鎖的執行緒解鎖為止
  • 遞迴互斥鎖能夠成功地返回並且增加呼叫執行緒在互斥上加鎖的次數
  • 檢錯互斥鎖則為快速互斥鎖的非阻塞版本,它會立即返回並返回一個錯誤資訊

2. 互斥鎖的操作步驟

  • 定義互斥鎖變數:pthread_mutex_t
  • 定義互斥鎖屬性變數:pthread_mutexattr_t
  • 初始化互斥鎖屬性變數:pthread_mutexattr_init();
  • 設定互斥鎖屬性:pthread_mutexattr_settype、pthread_mutexattr_setpshared、pthread_mutexattr_gettype、pthread_mutexattr_getpshared、pthread_mutexattr_destroy;
  • 初始化互斥鎖變數:pthread_mutex_init();
  • 互斥鎖上鎖:pthread_mutex_lock();
  • 互斥鎖判斷上鎖:pthread_mutex_trylock();
  • 互斥鎖解鎖:pthread_mutex_unlock();
  • 消除互斥鎖:pthread_mutex_destroy()

第六章

  1. 各種函式

總結

核心依然是一、二、三章;其中套接字部分最好將函式與引數一起記住;與此同時掌握迴圈套接字的流程以及程式編寫。對於後面的部分,個人認為大題概率不大(基本沒有),記一些重要的函式即可,其餘函式見名知意。