TCP Server和Client模型:linux
1 #include <sys/types.h> /* See NOTES */ 2 #include <sys/socket.h> 3 4 int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
做用是綁定addr中的<IP:PORT>, 對於tcp server通常port是固定的。當系統有多個IP(多網卡)時,把ip設置爲INADDR_ANY, 內核會自動分配ip。若是隻有單一的IP,選擇服務器
機器IP和INADDR_ANY效果是同樣的。app
客戶和服務器經過調用函數bind時能夠指定IP地址或端口號,能夠都指定,也能夠都不指定:異步
l 客戶端
1. TCP客戶端:socket
1) 當TCP客戶未綁定IP地址,當它調用connect時內核會根據外出接口給它綁定一個IP地址和一個臨時端口號。而且TCP服務器在接到這個鏈接後會以這個IP地址做爲迴應數據報的目的IP地址。 2) 當TCP客戶綁定了IP地址,它就爲發出的數據鏈接指定了一個源IP地址,而且TCP服務器在接到這個鏈接後會以這個IP地址做爲迴應數據報的目的IP地址。 3) TCP客戶只能根據四元組(原端口號,原IP地址,目的端口號,目的IP地址)接受數據報。
2. UDP客戶端:tcp
1) 當UDP客戶未綁定IP地址,當它調用sendto時內核會根據外出接口給它綁定一個IP地址和一個臨時端口號。(UDP客戶能夠接收到達它綁定的臨時端口的任何UDP數據報)。 2) 當UDP客戶綁定了IP地址,它就爲發出的數據報指定了一個源IP地址,而且UDP服務器在接到這個數據報後會以這個IP地址做爲迴應數據報的目的IP地址。(UDP客戶只能接收到達它綁定的臨時端口而且目的地址爲它綁定的IP地址的UDP數據報)。 3) 當UDP客戶調用connect,內核記錄下對方的IP地址和端口號,它們包含在傳遞給connect的套接口地址結構中,併爲UDP客戶綁定了一個臨時端口號和IP地址。(UDP客戶只能接收目的IP地址爲它綁定的IP地址和端口號而且源IP地址爲它指定對方的IP地址和端口號的數據報)。
l 服務器端
1. TCP服務器:ide
1) 當TCP服務器綁定通配IP地址,套接口會接收到達它綁定端口的任何TCP鏈接。並以接收的目的IP地址做爲它的源IP地址(用以肯定四源組),以接收的源IP地址做爲它的目的IP地址發回應答。 2) 當TCP服務器綁定本地IP地址,這就限制了套接口只接收到達它綁定端口而且目的地址爲此IP地址的客戶鏈接。以綁定的目的IP地址做爲源IP地址(固然,綁定的IP地址確定與接收鏈接的目的IP地址相同,不然它不會接收),並以接收的源IP地址做爲它的目的IP地址發回應答。
通常只有在本機有多個網卡(多IP)纔有效。如服務器SERVER有IP地址IPA和IPB,服務bind了IPA,那麼發送給IPB的數據SERVER不會接收。若是是bind IPADDR_ANY, 則發到該服務器上的請求都會接受。
2. UDP服務器:函數
1) 當UDP服務器綁定通配IP地址,套接口會接收到達它綁定端口的任何UDP數據報。並以數據報的外出接口的主IP地址爲源IP地址,以接收到的源IP地址做爲它的目的IP地址發回應答。 2) 當UDP服務器綁定本機IP地址,這就限制了套接口只接收到達它綁定端口而且目的地址爲此IP地址的UDP數據報。並以綁定的IP地址做爲源IP地址,以接收的源IP地址做爲它的目的IP地址發回應答。 3) 當UDP服務器調用connect,內核記錄下對方的IP地址和端口號,它們包含在傳遞給connect的套接口地址結構中,併爲UDP服務器綁定了一個臨時端口號和IP地址。(UDP服務器只能接收目的IP地址爲它綁定的IP地址和端口號而且源IP地址爲它指定對方的IP地址和端口號的數據報)。
二、connect函數this
1 #include <sys/types.h> /* See NOTES */ 2 #include <sys/socket.h> 3 4 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
對於客戶端的 connect() 函數,該函數的功能爲客戶端主動鏈接服務器,創建鏈接是經過三次握手,而這個鏈接的過程是由內核完成,不是這個函數完成的,這個函數的做用僅僅是通知 Linux 內核,讓 linux 內核自動完成 TCP 三次握手鏈接,最後把鏈接的結果返回給這個函數的返回值(成功鏈接爲0, 失敗爲-1)。spa
一般的狀況,客戶端的 connect() 函數默認會一直阻塞,直到三次握手成功或超時失敗才返回(正常的狀況,這個過程很快完成)。
三、
listen() 函數的主要做用就是將套接字( sockfd )變成被動的鏈接監聽套接字(被動等待客戶端的鏈接), listen()函數不會阻塞,它主要作的事情爲,將該套接字和套接字對應的鏈接隊列長度告訴 Linux 內核,而後,listen()函數就結束。
這樣的話,當有一個客戶端主動鏈接(connect()),Linux 內核就自動完成TCP 三次握手,將創建好的連接自動存儲到隊列中,如此重複。
因此,只要 TCP 服務器調用了 listen(),客戶端就能夠經過 connect() 和服務器創建鏈接,而這個鏈接的過程是由內核完成。
關於backlog,Linux內核中維護兩個隊列:SYN_queue(SYN報文接收)和 ACCEPT queue(Established, Server收到ACK,三次握手完成)
a) When a connection request arrives (i.e., the SYN segment), the system-wide parameter net.ipv4.tcp_max_syn_backlog is checked (default 1000).
If the number of connections in the SYN_RCVD state would exceed this threshold, the incoming connection is rejected
客戶端connect發送SYN請求,服務端內核先檢查是否超過了SYN,沒有超過則加入到SYN queue,服務器的 SYN 響應,其中稍帶對客戶 SYN 的 ACK(即SYN+ACK)
b)Each listening endpoint has a fixed-length queue of connections that have been completely accepted by TCP (i.e., the three-way handshake is complete) but not yet accepted by the application
Accept queue中的tcp鏈接是內核創建完三次握手,可是應用程序尚未調用accept取出連接。這個隊列的大小就是backlog
The application specifies a limit to this queue, commonly called the backlog. This backlog must be between 0 and a system-specific maximum called net.core.somaxconn,
inclusive (default 128)
backlog has no effect whatsoever on the maximum number of established connections allowed by the system, or on the number of clients that a concurrent server can handle concurrently.
accept queue和最大tcp鏈接數無關
c)If there is room on this listening endpoint’s queue for this new connection, the TCP module ACKs the SYN and completes the connection. The server application with the listening endpoint does not see this new connection until the third segment of the three-way handshake is received.
若是SYN隊列未滿,TCP接收SYN請求並返回SYN的ACK,服務器並不感知這一過程。
Also, the client may think the server is ready to receive data when the client’s active open completes successfully, before the server application has been notified of the new connection. If this happens, the server’s TCP just queues the incoming data.
客戶端在Connect返回成功後(三次握手完成,連接已經進入服務端的Accept隊列),就認爲服務端準備好接收數據。此時服務端可能沒有調用Accept函數把連接從Accept隊列取出。此時服務端tcp內核只是把數據存入緩衝區。
d) If there is not enough room on the queue for the new connection, the TCP delays responding to the SYN, to give the application a chance to catch up .it persists in not ignoring incoming connections if it possibly can .
若是SYN隊列滿,TCP延遲響應客戶端SYN請求。此時客戶端會超時重試。
If the net.ipv4.tcp_abort_on_overflow system control variable is set, new incoming connections arereset with a reset segment.
若是服務端開啓net.ipv4.tcp_abort_on_overflow,該SYN請求會被拒絕,服務端發送RST報文。
2、select/epoll區別