天天看點

好教程推薦系列:TCP面試常見題-張小方的知乎Live-輕松搞定技術面試中常見的網絡通信問題(一)

先聲明一下,文章是我自己整理的筆記,内容是張小方先生的講稿。歡迎關注張先生主持的【高性能伺服器開發】WeChat gongzhong号。

張先生的部落格位址是

http://blog.csdn.net/analogous_love 張小方 的知乎 Live:輕松搞定技術面試中常見的網絡通信問題 https://www.zhihu.com/lives/922110858308485120?utm_source=qq&utm_medium=social

本live列舉的這些網絡問題涵蓋了技術面試中關于網絡通信的80%的面試題,深入了解并掌握這些原理,不僅能幫您寫出高品質的網絡通信程式,同時能應付面試中絕大多數網絡通信題目,助您的升職加薪一臂之力。

本次 Live 主要包括以下内容 • TCP/IP協定棧層次與三次握手、四次揮手需要知道的細節 • TCP與UDP适用場景 • linux網絡模型 • epoll_event結構中epoll_data_t的fd與ptr使用場景 •Windows網絡模型 •異步connect •select可以檢測網絡異常嗎 •epoll的水準模式和邊緣模式 •阻塞與非阻塞socket的設定與差別 •send/recv傳回值問題 •如何編寫正确的收與發資料代碼 •收發緩沖區如何設計 •SO_SNDTIMEO、SO_RCVTIMEO、TCP_NODELAY、SO_REUSEADDR和SO_REUSEPORT、SO_LINGER選項 •shutdown與優雅關閉 •錯誤碼EINTR •tcp粘包問題 •信号SIGPIPE與EPIPE錯誤碼 •gethostbyname阻塞與錯誤碼 •SO_KEEPALIVE選項與心跳包設計技巧 •如何設計斷線重連機制 •如何清除無效的死鍊 •網絡架構中定時器不同實作 •http協定格式、head、get與post方法細節 •http、socks4與socks5代理編碼實作 •你問我答互動環節 •總結

技術面試中常見的網絡通信細節問題解答

1. TCP/IP協定棧層次結構

2. TCP三向交握需要知道的細節點

3. TCP四次揮手需要知道的細節點(CLOSE_WAIT、TIME_WAIT、MSL)

4. TCP與UDP的差別與适用場景

5. linux常見網絡模型詳解(select、poll與epoll)

6. epoll_event結構中的epoll_data_t的fd與ptr的使用場景

7. Windows常見的網絡模型詳解(select、WSAEventSelect、WSAAsyncSelect)

8. Windows上的完成端口模型(IOCP)

9. 異步的connect函數如何編寫

10.select函數可以檢測網絡異常嗎?

11.你問我答環節一

12. epoll的水準模式和邊緣模式

13. 如何将socket設定成非阻塞的(建立時設定與建立完成後設定),非阻塞socket與阻塞的socket在收發資料上的差別

14. send/recv(read/write)傳回值大于0、等于0、小于0的差別

15.如何編寫正确的收資料代碼與發資料代碼

16.發送資料緩沖區與接收資料緩沖區如何設計

17.socket選項SO_SNDTIMEO和SO_RCVTIMEO

18.socket選項TCP_NODELAY

19.socket選項SO_REUSEADDR和SO_REUSEPORT(Windows平台與linux平台的差別)

20.socket選項SO_LINGER

21.shutdown與優雅關閉

22.你問我答環節二

23.socket選項SO_KEEPALIVE

24.關于錯誤碼EINTR

25.如何解決tcp粘包問題

26.信号SIGPIPE與EPIPE錯誤碼

27.gethostbyname阻塞與錯誤碼擷取問題

28.心跳包的設計技巧(保活心跳包與業務心跳包)

29.斷線重連機制如何設計

30.如何檢測對端已經關閉

31.如何清除無效的死鍊(端與端之間的線路故障)

32.定時器的不同實作及優缺點

33.你問我答環節三

34.http協定的具體格式

35.http head、get與post方法的細節

36.http代理、socks4代理與socks5代理如何編碼實作

37.ping

38.telnet

39.你問我答環節四

40.總結

--------------------------------------------------------------------------------------

好教程推薦系列:TCP面試常見題-張小方的知乎Live-輕松搞定技術面試中常見的網絡通信問題(一)

答:1、三次握手,如果前兩次有某一次失敗,會重新從第一次開始,重來三次。

2、三次握手,如果最後一次失敗,伺服器并不會重傳ack封包,而是直接發送RTS封包段,進入CLOSED狀态。這樣做的目的是為了防止SYN洪泛攻擊。詳情參見

http://blog.csdn.net/libaineu2004/article/details/79020031

3、發起連接配接時如果發生TCP SYN丢包,那麼系統預設的重試間隔是3s,這期間不會傳回錯誤碼。

4、如何模拟tcp揮手失敗?答案是iptables指令可以過濾資料包,丢棄所有的連接配接請求,緻使用戶端無法得到任何ack封包。

TCP 的那些事兒(上) TCP 的那些事兒(下) 答: http://blog.csdn.net/libaineu2004/article/details/78886213 再談應用環境下的TIME_WAIT和CLOSE_WAIT http://blog.csdn.net/libaineu2004/article/details/78886182 CLOSE_WAIT狀态的原因與解決方法 http://blog.csdn.net/libaineu2004/article/details/78803068

TCP面試常見題:time_wait狀态産生的原因,危害,如何避免

答:TCP協定棧本身是可靠,不會丢包,不會亂序,失敗會重發。UDP需要應用層做協定來保證可靠性。視訊可以用UDP。

必須使用udp的場景:廣播。

答:select和poll本質上沒有差別,都是輪詢,但是poll沒有最大裝置描述符數量的限制。

答:在epoll模型中使用了一個struct epoll_event的結構體:

typedef union epoll_data 
{ void *ptr;
 int fd; 
 uint32_t u32;
 uint64_t u64;
 } epoll_data_t; 
struct epoll_event 
{ uint32_t events; /* Epoll events */ 
 epoll_data_t data; /* User data variable */
 };      

參考部落格:

http://blog.csdn.net/analogous_love/article/details/60761528
好教程推薦系列:TCP面試常見題-張小方的知乎Live-輕松搞定技術面試中常見的網絡通信問題(一)
//關于tcp連接配接的異步connect實作流程如下:  
//(1)設定socket連接配接為非阻塞.  
//(2)調用connect函數.傳回0表明連接配接成功.如果傳回-1,同時errno為EINPROGRESS表明正在建立連接配接.  
//(3)使用select , epoll等 , 當描述符可寫的時候檢查連接配接狀态.  
  
#include <stdio.h>  
#include <fcntl.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <errno.h>  
#include <sys/epoll.h>  
#include <netinet/in.h>  
#include <string.h>  
  
void setnonblock(int fd)  
{  
    int flags = fcntl(fd, F_GETFL);  
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);  
}  
  
int main(){  
    const char* ip = "127.0.0.1";  
    short port = 9999;  
      
    //設定連接配接位址  
    struct sockaddr_in addr;  
    socklen_t socklen = sizeof(struct sockaddr_in);  
    memset(&addr , 0 , sizeof(struct sockaddr_in));  
    addr.sin_family = AF_INET;  
    addr.sin_addr.s_addr = inet_addr(ip);  
    addr.sin_port = htons(port);  
      
    //建立描述符  
    int fd = socket( AF_INET , SOCK_STREAM , 0);  
    if (fd < 0){  
        printf("socket() error\n");  
        return -1;  
    }  
    //設定描述符為非阻塞  
    setnonblock(fd);  
      
    //連接配接  
    int res;  
    res = connect(fd , (struct sockaddr*)&addr , socklen);  
    if (res == 0){  
        printf("connect ok(1)\n");  
    } else if (res == -1 && errno != EINPROGRESS){  
        printf("connect err(1)\n");  
        close(fd);  
        return -1;  
    } else {  
        int epfd;  
        //建立epoll描述符  
        epfd = epoll_create(1024);  
        if ( (epfd = epoll_create(1024) ) == -1){  
            printf("epoll_create() err\n");  
            close(fd);  
            return -1;  
        }  
        //添加關注事件  
        struct epoll_event ev;  
        ev.events = EPOLLOUT;  
        ev.data.fd = fd;  
        epoll_ctl( epfd , EPOLL_CTL_ADD , fd , &ev);  
          
        //編寫網絡程式的時候,epoll是程式的主循環.我們這裡為了測試,連接配接上或connect逾時(75秒)就break掉.  
        //正常的流程是寫一個處理connect結果的回調函數.  
        int event_max = 1;  
        struct epoll_event events[event_max];  
        int i;  
        while (1){  
            res = epoll_wait( epfd , events , event_max , -1);  
            if (res > 0){  
                for ( i = 0 ; i < res ; i++){  
                    if ( events[i].data.fd == fd && ( events[i].events & EPOLLOUT) ){ //29(EPOLLOUT|EPOLLERR|EPOLLHUP)  //4(EPOLLOUT)  
                        //檢查是否連接配接成功  
                        int optval;  
                        socklen_t optlen = sizeof(optval);  
                        int res1 = getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optlen);  
                        if ( res1 < 0 || optval){  
                            close(fd);  
                            close(epfd);  
                            printf("connect err(2)\n");  
                            return -1;  
                        } else {  
                            printf("connect ok(2)\n");  
                        }  
                    }  
                }  
                break;  
            }  
        }  
        close(fd);  
        close(epfd);  
    }  
}  

      

繼續閱讀