網(wǎng)絡(luò)筆記

網(wǎng)絡(luò):

1.?OSI模型?

????*?物理層:硬件連接的接口。

????*?數(shù)據(jù)鏈路層:?通信道的無差錯傳輸,提供數(shù)據(jù)成幀。

????*?網(wǎng)絡(luò)層:?將數(shù)據(jù)正確并且迅速的從原點主機(jī)傳送到目的主機(jī)。

????*?傳輸層:?掩蓋下層結(jié)構(gòu)細(xì)節(jié),保證會話層的消息正確的傳輸?shù)搅硪环降臅拰印?/p>

????*?會話層:?實現(xiàn)兩端主機(jī)之間的會話管理。

????*?表示層:?信息轉(zhuǎn)換,壓縮,解密,代碼轉(zhuǎn)換。

????*?應(yīng)用層:?提供日常的應(yīng)用。

2.?網(wǎng)絡(luò)?

網(wǎng)絡(luò)連接也是一個文件,它也有文件描述符!

stdin:0?標(biāo)準(zhǔn)輸入

stdout:1?標(biāo)準(zhǔn)輸出

數(shù)據(jù)傳送不會消失,順序傳送,發(fā)送和接收非同步。

TCP/IP

TCP:保證數(shù)據(jù)的可靠性,和正確性。

IP:控制數(shù)據(jù)如何從源頭到達(dá)目的地。

3.?進(jìn)程?

??正在執(zhí)行的程序被稱為進(jìn)程,進(jìn)程樹頂端是init控制進(jìn)程。

*?fork()?調(diào)用進(jìn)程創(chuàng)建新的進(jìn)程。

*?wait()?進(jìn)程同步措施,使一個進(jìn)程等待進(jìn)程,到另一個進(jìn)程結(jié)束為止。

*?exit()?終止一個進(jìn)程的運行。

*?exec()?系統(tǒng)調(diào)用。

pid_t?fork(void);?//?創(chuàng)建一個進(jìn)程,返回進(jìn)程id是pid_t類型。

4.?TCP和UDP?

tcp:可靠的通信傳輸,面向連接,面向字節(jié)流,數(shù)據(jù)傳輸慢。

udp:不需要建立連接,不可靠通信傳輸,面向報文,速度快。

5.?常見端口及對應(yīng)服務(wù)?

21????FTP文件傳輸協(xié)議

22????SSH

23????Telnet

80????HTTP超文本傳輸協(xié)議

6379??redis默認(rèn)端口

6.?tcp三次握手?

??*?客戶端發(fā)送請求SYN報文段到服務(wù)器,進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器確認(rèn)。??????發(fā)送?SYN=1?seq=client_isn

??*?服務(wù)器收到SYN進(jìn)行確認(rèn),回復(fù)給客戶端,進(jìn)入SYN_RECV狀態(tài)。?????????????????發(fā)送?SYN=1?seq=server_isn??ack=client_isn+1

??*?客戶端收到SYN_ACK報文段,進(jìn)入ESTABLISHED狀態(tài),完成三次握手。????????????發(fā)送?SYN=0?seq=clien_isn+1?ack=server_isn+1

7.?tcp四次揮手?

??*?客戶端發(fā)送連接釋放報文,停止發(fā)送數(shù)據(jù),進(jìn)入終止等待狀態(tài)?1?????????????????發(fā)送?FIN=1?seq=client_isn????????????????

??*?服務(wù)器收到報文,發(fā)出確認(rèn)報文ack帶上自己序列號seq,進(jìn)入等待關(guān)閉狀態(tài)???????發(fā)送??ack=client_isn+1??seq=server_isn

????*?客戶端收到服務(wù)器報文后,進(jìn)入終止等待狀態(tài)?2

??*?服務(wù)器發(fā)送完數(shù)據(jù)后,向客戶端發(fā)送釋放報文,自身進(jìn)入最后確認(rèn)狀態(tài)。??????????發(fā)送?FIN=1?ack=client_isn+1?seq=server_isn

??*?客戶端收到確認(rèn)后,發(fā)送最后確認(rèn),進(jìn)入wait狀態(tài),等待2*MSL時間。????????????發(fā)送?ack=server_isn+1?seq=client_isn+1

????*?服務(wù)器收到客戶端發(fā)出的確認(rèn),立即進(jìn)入close狀態(tài)。

8.?為什么結(jié)束連接的TIME_WAIT需要等待2MSL才能返回close狀態(tài)?

客戶端發(fā)送的最后一步的確認(rèn),不完全是可靠的,網(wǎng)絡(luò)可能存在別的異常情況。

所以客戶端會進(jìn)入TIME_WAIT狀態(tài),設(shè)置定時器,如果服務(wù)器一直發(fā)送第三步消息,client會再次發(fā)送確認(rèn)信息,并繼續(xù)等待2MSL時間。

2MSL:網(wǎng)絡(luò)的最大存活時間,一個發(fā)送和一個回復(fù)所需的最大時間。

直到服務(wù)器收到最后確認(rèn),不再發(fā)送FIN消息,就知道已經(jīng)被成功接收,結(jié)束tcp連接。

9.?建立了連接,客戶端故障。

tcp存在?;钣嫊r器。?服務(wù)器在既定時間(2h)沒有收到客戶端的任何消息。然后每隔一段時間(75s)發(fā)送一個探測報文段。

如果一連10次都沒有反應(yīng),將自動關(guān)閉這個連接。

10.?IP地址分類。

A???1.0.0.1?-?127.255.255.254

B???128.0.0.1?-?191.255.255.254

C???192.0.0.1?-?223.255.255.254

D???224.0.0.0?-?239.255.255.255

E???保留用于實驗使用

11.?tcp比udp慢的原因?

*?收發(fā)數(shù)據(jù)前后進(jìn)行的連接設(shè)置及清除過程。

*?收發(fā)過程中為保證數(shù)據(jù)可靠性添加的流控制。

12.?udp的傳輸函數(shù):

ssize_t?sendto(int?sock,?void?*buff,?size_t?nbytes,?int?flags,?struct?sockaddr?*to,?socklen_t?addrlen);

sock:?創(chuàng)建的套接字

buff:?傳輸數(shù)據(jù)的緩沖地址值。

nbytes:?待傳輸?shù)淖止?jié)數(shù)據(jù)

flags:?可選項參數(shù),無則是0

to:?發(fā)送對象地址。

addrlen:地址結(jié)構(gòu)體長度

13.?udp的接收函數(shù)?

ssize_t?recvfrom(int?sock,?void?*buff,?size_t?nbytes,?int?flags,?struct?sockaddr*?from,?socklen_t?addrlen);

和上面基本信息一樣。

14:udp

不存在請求和連接,因此某種意義上說,不區(qū)分服務(wù)器和客戶端。

15:回聲消息,read和write

tcp在發(fā)送數(shù)據(jù)時候,如果數(shù)據(jù)過大,會分包發(fā)送,如果write和read是同時進(jìn)行的,那么會存在,write還沒有把數(shù)據(jù)全部發(fā)送到服務(wù)器,

服務(wù)器回復(fù)一部分?jǐn)?shù)據(jù)時,read讀取會出現(xiàn)問題。

16.?什么是協(xié)議?

網(wǎng)絡(luò)中交換數(shù)據(jù)的標(biāo)準(zhǔn)規(guī)則,約定的集合。

17.?大端小端?

大端:高位字節(jié)存放到低位地址。

小端:高位字節(jié)存放到高位地址。

*?程序判斷:int?i?=?0x12345678?char?*c?=?(char?*)&i;?c[0]?==?0x12?小端

*?typedef?union?{

*???int?i;

*???char?c;

*?}?myunion;

*?myunion.i?=?1;?return?myunion.i?==?myunion.c

18.?tcp和udp的4層協(xié)議棧?經(jīng)過的層級結(jié)構(gòu)差異

應(yīng)用層,?tcp/udp層,IP層,鏈路層。

19.?write和read函數(shù)。

write和read交互,write可以直接一次性將數(shù)據(jù)發(fā)送到另一端,但是read不一定能全部讀取,因為數(shù)據(jù)量太大的情況下,read讀不全數(shù)據(jù)。

20.?udp

tcp在不可靠的IP層進(jìn)行流控制,udp缺少這種流控制。

tcp和udp最基本的區(qū)別就是流控制,其它區(qū)別所剩無幾。

21.?壓縮文件傳輸。

壓縮文件必須選擇tcp進(jìn)行傳輸,如果中途有數(shù)據(jù)丟失,解壓就會失敗,所以必須是選擇tcp進(jìn)行傳輸。

22.?gethostbyname?通過域名轉(zhuǎn)換為IP

struct?hostent{

??char?*h_name;????????//?office?name?官方域名

??char?**h_aliases;????//?alias?list?同一IP可以綁定多個域名,出官方域名,還有其它域名。

??int?h_addrtype;??????//?IP地址族信息,

??int?h_length;????????//

??char?**h_addr_list;??//?IP

}

23.?Nagle算法。tcp?消息。

只有收到前一數(shù)據(jù)的ACK消息時,Nagle算法才發(fā)送下一次數(shù)據(jù)。

開啟Nagle算法時候,會合理的減少流量,但是傳輸速度會降低。

關(guān)閉Nagle算法時候,會增加網(wǎng)絡(luò)流量,傳輸速度會增加,尤其是在大數(shù)據(jù)量的傳輸中,這種速度會很明顯。

注:未準(zhǔn)確判斷數(shù)據(jù)特性時不應(yīng)禁用Nagle算法。

禁用Nagle算法:?int?opt_val?=?1

開啟Nagle算法:?int?opt_val?=?0

setsockopt(sock,?IPPROTO_TCP,?TCP_NODELAY,?(void*)&opt_val,?sizeof(opt_val))

24.?并發(fā)服務(wù)器的實現(xiàn)。

多進(jìn)程服務(wù)器:?通過創(chuàng)建多個進(jìn)程提供服務(wù)。

多路復(fù)用服務(wù)器:?通過捆綁并統(tǒng)一管理I/O對象提供服務(wù)。

多線程服務(wù)器:?通過生成與客戶端等量的線程提供服務(wù)。

25.?進(jìn)程和子進(jìn)程

fork創(chuàng)建進(jìn)程之后,父進(jìn)程返回子進(jìn)程的進(jìn)程ID

子進(jìn)程返回0.

父子進(jìn)程,只共享一段代碼,有不同的數(shù)據(jù)存儲空間。

26.?僵尸進(jìn)程

子進(jìn)程比父進(jìn)程先結(jié)束,父進(jìn)程又沒有回收子進(jìn)程,釋放子進(jìn)程占用的資源。

應(yīng)向創(chuàng)建子進(jìn)程的父進(jìn)程傳遞子進(jìn)程的exit參數(shù)或return返回。

*?只有父進(jìn)程主動發(fā)起請求,操作系統(tǒng)才會傳遞該值。(父母要負(fù)責(zé)回收自己孩子。)

27.?wait函數(shù)

調(diào)用wait函數(shù)可以將終止的子進(jìn)程退出。wait函數(shù)會阻塞等待,直到有子進(jìn)程退出。

WIFEXITED?子進(jìn)程正常終止時返回?true

WEXITSTATUS?返回子進(jìn)程的返回值

28.?waitpid函數(shù)

wait函數(shù)會引起程序阻塞。waitpid(pid_t,?pid,?int?*?statloc,?int?options);成功返回終止的子進(jìn)程ID,失敗返回-1

參數(shù):?pid?等待目標(biāo)子進(jìn)程,若為-1,則可以等待任意子進(jìn)程退出。

statloc:?status??options:?WNOHANG即使沒有終止的子進(jìn)程,也不會進(jìn)入阻塞狀態(tài)。

29.?信號。

void?(*signal(int?signo,?void(*func)(int)))(int);

void?function(int?flag)?{}

調(diào)用signal?signal(SIGNO,?function)

接收第二個參數(shù)是一個函數(shù)指針(地址),函數(shù)的參數(shù)是int類型,返回值是void

30.??信號的高級用法:

??struct?sigaction?act;

??act.sa_handler?=?read_childproc;??

??sigemptyset(&act.sa_mask);??

??act.sa_flags?=?0;?????

??sigaction(SIGCHLD,&act,0);??//注冊信號,觸發(fā)SIGCHILD信號后將會調(diào)用act函數(shù)

??return?和?exit將會觸發(fā)到該信號。

??read_childproc函數(shù)如下:

??void?read_childproc(int?sig){??

??????int?status;??


??????pid_t?id?=?waitpid(-1,?&status,?WNOHANG);??


??????if(WIFEXITED(status)){??

????????printf("Removed?proc?id?:?%d?\n",id);??

????????printf("child?send?:?%d?\n",WEXITSTATUS(status));??

??????}???

??}

31.?進(jìn)程間通信->pipe

int?pipe(int?fileds[2])?fileds[0]?出口,?fileds[1]?入口

test:

??int?fds[2];?pipe(fds);?fork一個父進(jìn)程,和子進(jìn)程,子進(jìn)程寫數(shù)據(jù)到文件,父進(jìn)程從文件讀數(shù)據(jù),就實現(xiàn)了進(jìn)程間通信、

32.?fread和read

fread是C語言的庫,read是系統(tǒng)調(diào)用。

?read每次讀取要求大小的數(shù)據(jù),從用戶態(tài)切換到內(nèi)核態(tài)(損耗性能)

?fread每次從內(nèi)核緩沖區(qū)讀取較多的數(shù)據(jù),放到應(yīng)用進(jìn)程緩沖區(qū),下次再取直接去應(yīng)用進(jìn)程緩沖區(qū)取,不用消耗太多性能。

?33.?fwrite和write

?write是系統(tǒng)調(diào)用,每次需要將數(shù)據(jù)寫到磁盤,寫的大小是要求的大小,依然涉及頻繁的用戶態(tài)和內(nèi)核態(tài)切換。

?fwrite是庫函數(shù),每次講數(shù)據(jù)寫入到換乘區(qū),等緩沖區(qū)滿了,一次寫入磁盤?;蛘呤褂胒flush沖洗緩沖區(qū)。

?34.?sigaction?捕捉信號的類型

??????struct?sigaction?{

??????????void?(*sa_handler)(int);??//?信號處理函數(shù)

??????????void?(*sa_sigaction)(int,?siginfo_t?*,?void?*);

??????????sigset_t?sa_mask;?????????//?設(shè)置處理該信號時,暫時將sa_mask指定信號擱置

??????????int?sa_flags;?????????????//?信號其它相關(guān)操作。

??????????void?(*sa_restorer)(void);??//?

??????}

??注:聯(lián)合?信號的高級用法使用

35.?使用多任務(wù)并發(fā)服務(wù)器

??fork出來的子進(jìn)程,需要關(guān)閉ser_sockID?只保留父進(jìn)程的ser_sockID,持續(xù)去accept客戶端的連接。

??父進(jìn)程,只負(fù)責(zé)接收客戶端的連接,客戶端的cli_sockID?也需要關(guān)閉。

36.?I/O復(fù)用.

??select?將多個文件描述符,集中到一起進(jìn)行監(jiān)控。

??fd_set?set;?FD_ZERO,?清零。?FD_SET?設(shè)置1,?FD_CLR?單個清零。

37.?select函數(shù)

int?select(int?maxfd,?fd_set?*readset,?fd_set?*writeset,?fd_set?*exceptset,?const?struct?

timeval?*timeout)

調(diào)用select函數(shù)后,除了發(fā)生變化的描述符外,剩下的所有位都將被初始化為0。

38.?select使用。

在進(jìn)行select使用時候,需要維護(hù)兩個描述符集合(use,copy),兩個內(nèi)容一樣。

復(fù)制的copy,用作select調(diào)用傳入,當(dāng)有收到消息時候,copy內(nèi)除了有消息的描述符,其它都被置0。

所以只需要循環(huán)檢查,F(xiàn)D_ISSET?文件描述符是否存在copy中,如果存在,就證明這個有消息了。開始處理吧。

39.?多播(組播)、廣播.

int?so_ard?=?1

廣播:?setsockopt(sockid,?SOL_SOCKET,?SOL_BORADCAST,?(void?*)&so_ard,?sizeof(so_ard))

40.?標(biāo)準(zhǔn)IO的缺點

*?不容易進(jìn)行雙向通信

*?有時可能需要頻繁的調(diào)用fflush

*?需要以FILE結(jié)構(gòu)體指針的形式返回文件描述符

41.?select的弊端

無論如何優(yōu)化程序性能,也無法同時接入上百個客戶端,select不適合以web服務(wù)器端。

42.?select函數(shù)

每次調(diào)用select函數(shù)時,向操作系統(tǒng)傳遞檢視對象信息。

僅向操作系統(tǒng)傳遞1次監(jiān)視對象,監(jiān)視的范圍發(fā)生變化時,只通知發(fā)生變化的事項。

43.?epoll的優(yōu)點

無需編寫以檢視狀態(tài)變化為目的的針對所有文件描述符的循環(huán)語句。

調(diào)用對于select函數(shù)的epoll_wait函數(shù)時,無需每次傳遞檢視對象信息。

44.?epoll需要的3個函數(shù)

epoll_create?創(chuàng)建保存epoll文件描述符的空間

epoll_ctl?想空間注冊并注銷文件描述符

epoll_wait?與select函數(shù)類似,等待文件描述符發(fā)生變化

45.?select和epoll不同點

select需要FD_SET,?FD_CLR函數(shù)。????????epoll需要通過epoll_wait函數(shù)。

select下調(diào)用select函數(shù)等待描述符變化。?epoll中調(diào)用epoll_wait函數(shù)。

select下通過fd_set查看檢視對象的變化。?epoll中通過結(jié)構(gòu)體epoll_event將發(fā)生變化的文件描述符幾種到一起。

struct?epoll_event?{

??__unit32_t?events;

??epoll_data_t?data;

}

46.?epoll_create(int?size)函數(shù)

epoll_create創(chuàng)建的文件描述符保存空間稱為"epoll例程",?

參數(shù)size的值,決定epoll例程的大小。

47.?epoll_ctl

生成epoll例程后,在內(nèi)部注冊監(jiān)視對象文件描述符,使用epoll_ctl函數(shù)。

epoll_ctl(int?epfd,?int?op,?int?fd,?struct?epoll_event?*?event)

op參數(shù)的模型如下?

?*?EPOLL_CTL_ADD?注冊到例程中

?*?EPOLL_CTL_DEL?例程中刪除文件描述符

?*?EPOLL_CTL_MOD?更改文件描述符的關(guān)注事件發(fā)生情況

?48.?epoll_wait

int?epoll_wait(int?fd,?struct?epoll_event*?events,?int?maxevents,?int?timeout)

epfd:?發(fā)生監(jiān)視范圍的epoll

events:?保存發(fā)生事件的文件描述符集合的結(jié)構(gòu)體地址值

maxevents:?第二個參數(shù)中保存最大的事件數(shù)

timeout:等待時間

epoll回聲服務(wù)器端

#include?<stdio.h>

#include?<stdlib.h>

#include?<string.h>

#include?<unistd.h>

#include?<arpa/inet.h>

#include?<sys/socket.h>

#include?<sys/epoll.h>

#define?BUFF_SIZE?100

#define?EPOLL_SIZE?50

int?main(int?argc,?char?*argv[])

{

????int?ser_sock,?cln_sock;

????struct?sockaddr_in?ser_adr,?cln_adr;

????socketlen_t?adr_sz;

????int?str_len,?i;

????char?buf[BUFF_SIZE];

????struct?epoll_event?*ep_events;

????struct?epoll_event?event;

????int?epfd,?event_cnt;

????ser_sock?=?socket(PF_INET,?SOCK_STREAM,?0);

????memset(&ser_adr,?0,?sizeof(ser_adr));

????ser_adr.sin_family?=?AF_INET;

????ser_adr.sin_addr.s_addr?=?htonl(INADDR_ANY);

????ser_adr.sin_port?=?htons(atoi(argv[1]));

????if(bind(ser_sock,?(struct?sockaddr*)&ser_adr,?sizeof(ser_adr))?==?-1)

??????error();

????if(listen(ser_sock,?5)?==?-1)

??????error();

????//?創(chuàng)建epoll的例程空間

????epfd?=?epoll_create(EPOLL_SIZE);?//?返回值和套接字相同,最后也需要close掉

????ep_events?=?malloc(sizeof(struct?epoll_event)*EPOLL_SIZE);?//?申請一個epoll空間池

????event.events?=?EPOLLIN;?//?需要讀取數(shù)據(jù)情況

????event.data.fd?=?ser_sock;?//?socket的文件描述符

????epoll_ctl(epfd,?EPOLL_CTL_ADD,?ser_sock,?&event);?//?添加一個事件

????while(1)

????{

??????//?返回發(fā)生事件的文件描述符數(shù),?event_cnt個數(shù)

??????event_cnt?=?epoll_wait(epfd,?ep_events,?EPOLL_SIZE,?-1);?

??????if(event_cnt?==?-1)

????????break;

??????for(i=0;?i<event_cnt;?i++)

??????{

????????if(ep_events[i].data.fd?==?ser_sock)?//?新的客戶端連接走這里。

????????{

??????????//?將新連接的客戶端fd加入到epoll例程中

??????????adr_sz?=?sizeof(cln_adr);

??????????cln_sock?=?accept(ser_sock,?(struct?sockaddr*)&cln_adr,?&adr_sz);

??????????event.events?=?EPOLLIN;

??????????event.data.fd?=?cln_sock;

??????????epoll_ctl(epfd,?EPOLL_CTL_ADD,?cln_sock,?&event);

??????????printf("connected?client:?%d\n",?cln_sock);

????????}

????????else

????????{

??????????//?實現(xiàn)和已連接的客戶端通信

??????????str_len?=?read(ep_events[i].data.fd,?buf,?BUFF_SIZE);

??????????if(str_len?==?0)

??????????{

????????????//?處理完事件之后,將其從例程中刪除。

????????????epoll_ctl(epfd,?EPOLL_CTL_DEL,?ep_events[i].data.fd,?NULL);

????????????close(ep_events[i].data.fd);

????????????printf("close?client:%d\n",?ep_events[i].data.fd);

??????????}

??????????else

??????????{

????????????write(ep_events[i].data.fd,?buf,?str_len);

??????????}

????????}

??????}

????}

????close(ser_sock);

????close(epfd);

????return?0;

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容