UNIX網絡編程總結四

socket:

  爲了執行網絡I/O,一個進程作的第一件事就是調用socket函數。緩存

  family指明協議族,type指明類型,除非在原始套接口,protocol通常爲0,並不是全部的family,type組合都是有效的。服務器

  socket函數在成功時返回一個小的非負整數值,稱爲套接口描述字。網絡

 

connect:

  客戶在調用函數connect前沒必要非得調用bind,必要時,內核會選擇ip地址和臨時端口。併發

  TCP套接口,connect會激活三路握手,成功或者出錯時返回。socket

  幾種錯誤:函數

  一、TCP客戶未收到SYN分節響應,返回ETIMEDOUT。接口

  二、服務器無服務等待連接,返回ECONNREFUSED。隊列

  三、客戶發出的SYN分節在中間路由器引起目的不可達ICMP錯誤,返回EHOSTENREACH或ENETUNREACH錯誤。進程

 

bind:

  給套接口分配一個本地協議地址。ip

  對於TCP,bind能夠指定端口號,能夠指定ip地址,能夠都指定,也能夠都不指定。

  若讓內核爲套接口選擇一個臨時端口,函數bind不返回所選的值,必須調用getsockname來返回協議地址。

 

listen:

  當函數socket建立一個套接口時,他被假設爲主動套接口,listen將未使用的套接口變爲被動套接口,告訴內核,此套接口能夠接受鏈接請求。

  內核要維護兩個隊列,兩隊列之和不超過backlog:

  一、未完成鏈接隊列,已有客戶發出併到達服務端,服務端等待完成三路握手,SYN_RCVD。

  二、已完成鏈接隊列,已完成三路握手,ESTABLISHED。

  Berkeley爲backlog增長模糊因子,1.5,即最大可支持值*1.5。

  不要把backlog定義爲0,由於不一樣實現有不一樣的解釋。

  當一個客戶SYN到達時,若隊列是滿的,則TCP忽略該分節,可是不發RST,客戶會重發該分節。

  套接字接收緩存區存儲握手完成但未accept時到達的數據。

 

accept:

  由TCP服務器調用,用於從已完成鏈接隊列隊頭返回下一個已完成鏈接,已完成鏈接爲空,進程進入睡眠。

  accept的第三個參數addrlen是值-結果參數,傳入套接口地址結構長度,返回內核存放在該套接字地址結構內的確切字節數。

  accept會返回一個內核生成的全新的描述符,表明所返回客戶的TCP鏈接,accept第一個參數稱爲監聽套接字描述符,返回的爲已鏈接套接字描述符,一個服務器通常只有一個監聽套接字描述符,但有不少已鏈接套接字描述符,它隨客戶鏈接建立,隨服務結束關閉。

 

fork和exec:

  # include <unisted.h>

  pid_t fork(void);

  fork調用一次返回兩次,父進程返回子進程的ID號,子進程返回0。

  父進程fork前打開的描述符在fork返回後由子進程共享。

  fork典型用法:

  一、建立自身進程的副本。

  二、一個進程執行另外一個程序,先建立自身副本,而後副本調用exec將自身替換爲新程序。

  exec:

  # include <unistd.h>

  int execl(const char *pathname, const char *arg0, ... /* (char *) 0 */);

int execv(const char *pathname, char *const *argv[]);

int execle(const char *pathname, const char *arg0, ... /* (char *) 0 , char *const envp[] */);

int execve(const char *pathname, char *const *argv[], char *const envp[]);

int execlp(const char *filename, const char *arg0, ... /* (char *) 0 */);

int execvp(const char *filename, char *const *argv[]);

進程調用exec前打開的描述符一般跨exec繼續保持打開,但可使用fcntl設置FD_CLOEXEC描述符標誌禁止掉。

 

併發服務器:

  鏈接創建,accept返回,服務器調用fork,而後由子進程服務客戶,父進程關閉已鏈接套接字,由於每一個文件或套接字都有引用計數器子進程會將其加1,父進程關閉不會致使計數器爲0,因此父進程關閉子進程不會終止客戶鏈接。父進程關閉已鏈接套接字後,就能夠繼續等待下一次鏈接了。

 

close:

  close一個TCP套接字的默認行爲是把該套接字標記爲已關閉,而後當即返回調用進程,該套接字描述符不能再由調用進程使用,但TCP仍然會嘗試發送已排隊等待發送到對端的任何數據,發送完畢後發正常TCP終止序列。

 

getsockname和getpeername

  getsockname返回某個套接字關聯的本地地址;

  # include <sys/socket.h>

  int getsocketname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);

  一、在未調用bind的TCP客戶上,connect成功返回,getsockname返回內核賦予該連接的本地IP地址和本地端口號。

  二、調用bind端口號爲0,返回內核賦予的本地端口號。

  三、獲取某套接字地址族。

  四、返回已通配地址bind的TCP服務的地址。

  

 getpeername返回某個套接字關聯的外地協議地址;

  # include <sys/socket.h>

  int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);

  當一個服務器是由調用過accept的某進程經過exec執行程序時,能夠經過getpeername獲取客戶身份。

相關文章
相關標籤/搜索