Linux網絡編程知識點總結
TCP/IP
基本套接字編程
TCP/UDP套接字編程
并發服務器
名字與地址轉換
網絡編程具體應用
原始套接字
TCP/IP
協議層次
三次握手機制
服務器必須準備好接收好客戶的連接請求,通過()、bind()、()函數來完成,客戶端調用()函數進行主動打開,客戶端向服務器發送一個SYN分節到服務器端服務器端收到客戶端發來的SYN分節后,必須發送ACK對其進行確認,同時發送一個SYN分節給客戶端,表示接收客戶端建立的連接請求客戶端發送ACK確認服務器的SYN,連接建立成功
基本套接字編程
字節排序函數
大小端概念:
小端字節排序:將低序字節存儲在起始位置
大端字節排序:將高序字節存儲早起始位置
操作函數:
htons:將16位的短整型數從主機字節序轉為網絡字節序
htonl:將32位的長整型數從主機字節序轉為網絡字節序
nhtons:將16位的短整型數從網絡字節序轉為主機字節序
nhtonl:將32位的長整型數從網絡字節序轉為主機字節序
如何判斷一個主機字節序
#include
using namespace std;
typedef union{
unsigned short value;
unsigned char bytes[2];
}Test;
int main(void)
{
Test test_value;
test_value.value=0x1234;
if(test_value.bytes[0]==0x12&&test_value.bytes[1]==0x34)
cout<<"大端排序"<<endl;
else if(test_value.bytes[0]==0x34&&test_value.bytes[1]==0x12)
cout<<"小端排序"<<endl;
else
cout<<"error"<<endl;
return 0;
}
套接字地址結構
typedef uint32_t in_addr_t;
typedef uint16_t in_port_t;
typedef unsigned short sa_family;
struct in_addr{
in_addr_t s_addr;
};
struct sockaddr_in
{
unint8_t sin_len;
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[0];
};
TCP/UDP套接字編程
套接字編程流程
流程:
服務器實現步驟:
使用()函數創建套接字將創建的套接字綁定到指定的地址結構()函數設置套接字為監聽模式,使服務器進入被動打開狀態接收客戶端的連接請求接收、應答客戶端的數據請求終止連接
客戶端實現步驟
使用()函數創建套接字調用()函數建立一個與TCP服務器的連接發送數據請求,接收服務器的數據應答終止連接
函數
socket
int socket(int family,int type,int protocol)
bind
int bind(int sockfd,const struct sockaddr * addr,socklen_len len)
listen
int listen(int sockfd,int backlog)
accept
int accept(int sockfd,struct sockaddr *cliaddr,sock_len * addrlen)
connect
int connect(int sockfd,const struct sockaddr *addr,socklen_t addlen)
read & write ,send & recv
close
并發服務器
服務器分類
服務器分類依據:處理方式分類
迭代式服務器
并發式服務器
多進程技術
多進程技術
進程是執行計算機程序,是在執行過程中不斷變化的動態實體,擁有自己的地址空間、執行堆棧、文件描述符等,每個進程都有一個非負整數作為唯一的進程ID,用來標識各個進程。
特點:父子進程占獨立地址空間,互補影響
Copy on Write技術
創建進程函數fork
pid_t fork(void)
父進程返回值:新派生的子進程ID號
子進程返回值:返回值為0
可以通過返回值來區別當前進程是子進程還是父進程
等待進程結束wait,
進程終止存在兩種可能性:父進程先于子進程終止和子進程先于父進程終止
終止信息(進程ID、進程終止狀態、進程使用CPU時間總量)
父進程調用wait()函數或()函數,系統內核可以釋放終止進程所使用的所有存儲空間,關閉所有打開的文件。
一個終止進程linux網絡編程原始套接字的魔力下,但是父進程未對其進行善后處理的進程稱為僵尸進程
父進程不回收,子進程變為孤兒進程
wait()
pid_t wait(int *statloc)
參數statloc返回子進程的終止狀態
pid_t waitpid(pid_t pid,int *statloc,int option)
pid=-1,option=0該函數等同于wait()函數
多線程技術
多線程優勢
創建線程函數
int pthread_create(pthread_t *tid,const pthread_attr_t *attr,void *(*func)(void *),void *arg)
參數tid返回新生成的進程ID{一個進程中的每個進程都由一個線程ID標識,其類型為}
attr指向線程屬性的指針{線程屬性:優先級、起始棧的大小、是否守護線程}
創建完一個新的線程后,需要說明它將執行的函數,函數的地址由參數func指定
該執行函數的調用是由arg指定的,arg是一個通用的指針,用于往func()函數中傳遞參數
等待線程結束函數
int pthread_join(pthread_t tid,void **status)
tid指定所等待的線程ID。該函數必須指定要等待的線程,不能等待任一個線程結束。
如果指針非空,則指向終止線程的退出狀態值
I/O多路復用
函數使用方法
()函數是最具有代表性的實現復用的服務端的方法
將多個文件描述符集中到一起進行統一監視
當監視到有文件描述符需要輸入或者輸出時就選擇該接口進行通訊
通訊完成之后就回到之前監視狀態
int select(int maxfd,fd_set * read_set,*write_set,fd_set *except_set,const struct timeval *timeout)
maxfd(監視數量):監視對象文件描述數量
(讀取文件描述集合的地址):將所有關注“是否存在待讀取數據”的文件描述符注冊到集合中,并傳遞地址值
(寫入文件描述集合的地址):將所有關注“是否可傳輸無阻塞數據”的文件描述符注冊到集合中
(發生異常文件描述符集合地址):將所有關注“是否發生異常”的文件描述符注冊到集合中
(超時):為防止無限進入阻塞狀態,設置一個超時信息
設置步驟:
參數設置
設置文件描述符
指定監聽范圍
設置超時
調用()函數:監聽注冊文件描述符的狀態,當狀態發生變化linux網絡編程原始套接字的魔力下,或者超時返回結果,查看調用結果
名字與地址轉換編程
DNS工作流程
遞歸查詢流程
如果主機所查詢的本地域名服務器不知道被查詢的域名IP地址,那么本地域名服務器就以DNS客戶身份向其它根域名服務器繼續發出查詢報文,而不是讓主機自己進行下一步查詢
因此,遞歸查詢返回查詢的查詢結果或者就是要查詢的IP地址,或者就是報錯,表示無法查到
迭代式查詢流程
當根域名服務器收到本地域名服務器發出的迭代查詢請求報文時,要么給出要查詢的IP地址,要么告訴本地服務器,你下一步應當向哪一個域名服務器進行查詢,后讓本地域名服務器進行后續查詢。根域名服務器通常是把自己知道的頂級域名服務器的IP地址告訴本地域名服務器,讓本地域名服務器再向頂級域名服務器查詢。頂級域名服務器在收到本地域名服務器的查詢請求后,要么給出所要查詢的IP地址,要么告訴本地服務器下一步應當向哪一個權限服務器進行查詢
最后,知道所要解析的IP地址或報錯,然后把這個結果返回給所要查詢的主機
dig +trace
地址轉換函數
gethostbyname
struct hostent * gethostbyname(const char*hostname)
是主機的域名地址,函數將查詢的結果作為參數返回。如果失敗返回空指針;如果成功,參數返回以下的結構
struct hostent{
char * h_name;//主機的正式名稱
char **h_aliases;//主機的別名列表
int h_addrtype;//主機地址類型
int h_length;//主機地址長度
char **h_addr_list;//主機IP地址的列表
};
# [0]在列表中的第一個地址
gethostbyaddr
struct hostent *gethostbyaddr(const char * addr,size_t len,int family)
addr一個真正指向含有Ipv4或Ipv6地址結構的指針
len是此結構的大小
為或
getaddr info
int getaddrinfo(const char * hostname,const char *service,const struct addrinfo * hints,struct addrinfo ** result)
該函數在庫函數中隱藏了所有協議依賴性,因此應用程序只需要處理由填寫的套接口地址結構即可
網絡編程的具體使用