TCP與SOCKET

三次握手

clipboard.png

四次揮手

clipboard.png

SOCKET

clipboard.png

在內核中,會維護兩個隊列:c++

  • 半鏈接隊列(syn隊列),存放處於SYN-RCVD狀態的socket
  • 全鏈接隊列(accept隊列),存放處於ESTABLISHED狀態的socket

accept函數會從全鏈接隊列裏取出一個鏈接,若是沒有則阻塞。這裏取出的是一個新的鏈接,叫已鏈接socket,不一樣於一開始建立的監聽socket。Socket在Linux中以文件的形式存在,有本身的文件描述符,讀寫就如同一個文件流。緩存

clipboard.png
socket結構裏有一個發送隊列和一個接收隊列,裏面保存着緩存sk_buff,裏面能夠看到完整的包結構。socket

數據接收流程

網卡接收到數據後寫入內存,並向CPU發起中斷,操做系統執行中斷程序喚醒對應socket等待隊列裏的進程。
如何同時監聽多個socket:函數

  • select

將進程放入全部須要監聽的socket的等待隊列裏,若是有一個socket接收到了數據就喚醒進程,而後遍歷socket列表查看是哪一個socket接收到了數據。spa

  • epoll
int epfd = epoll_create(...)
epoll_ctl(epfd, ...)
while(1){
    int n = epoll_wait(...)
    for (接收到數據的socket){
        //處理
    }
}

利用epoll_ctl將須要監視的socket添加到epoll_create建立的對象(eventpoll)中,而後利用epoll_wait進行阻塞,將進程放入eventpoll的等待隊列中。當有socket接收到數據,中斷程序將其被eventpoll的就緒列表所(rdllist)引用,而後喚醒進程,進程只須要遍歷就緒列表就能夠了。socket在eventpoll中利用紅黑樹存儲,而就緒列表利用雙向鏈表存儲。操作系統

相關文章
相關標籤/搜索