在講socket程式設計之前,先來回顧一下tcp的三握手與四揮手過程,這樣就更易理解socket程式設計了。
1.tcp三握手建立連線過程
2.tcp四揮手釋放連線過程
先來張圖,看看其過程如何:
針對上圖出現的函式或其它重要的函式,我在此解釋下:
1.socket():申請了乙個描述符(本地可見),但不能對外提供通訊
(1)函式
int socket(int domain , int type , int protocol);
(2)引數
2.bind():組合ip和埠,對外提供連線
(1)函式
int bind (int sockfd , struct sockaddr *my_addr , int addrlen)
(2)引數
3.listen():監聽繫結的ip埠上的資料,將半連線轉到全連線中
(1)函式
int listen(int sockfd, int backlog)
(2)引數
4.accept():從listen監聽的全連線佇列中取連線,申請檔案描述符,
(1)函式
int accept(int sockfd, void *addr, int *addrlen)
(2)引數
5.connect():連線到指定的ip
(1)函式
int connect (int sockfd, struct sockaddr *serv_addr, int addrlen)
(2)引數
6.write():寫入資料
(1)函式
ssize_t write(int fd, const void*buf,size_t nbytes)
(2)引數
(3)返回值
7.read():讀取資料
(1)函式
ssize_t read(int fd,void *buf,size_t nbyte)
(2)引數
(3)返回值
read() 函式會從 fd 檔案中讀取 nbytes 個位元組並儲存到緩衝區 buf,成功則返回讀取到的位元組數(但遇到檔案結尾則返回0),失敗則返回 -1。
8.send():傳送資料(通過tcp)
(1)函式
int send(int sockfd, const void *msg, int len, int flags)
(2)引數
9.recv():接收資料(通過tcp)
(1)函式
int recv(int sockfd, void *buf, int len, unsigned int flags)
(2)引數
10.close():關閉連線
(1)使用方法
close(sockfd)
(2)功能
執行close()之後,套接字將不會在允許進行讀操作和寫操作
(3)底層實現:引用計數
11.shutdown()
(1)函式
int shutdown(int sockfd, int how)
(2)引數
(3)how的方式
12.sendto():傳送資料(通過udp)
(1)函式
int sendto(int sockfd, const void *msg, int len, unsigned int flags,const struct sockaddr *to, int tolen);
(2)引數
13.recvfrom():接收資料(通過udp)
(1)函式
int recvfrom(int sockfd, void *buf, int len, unsigned int flags,struct sockaddr *from, int *fromlen)
(2)引數
1.乙個客戶端對外最多提供多少連線(一台伺服器最多接收多少埠)?
答:由核心記憶體上限(listen所能監聽的兩個佇列大小)和檔案描述符大小(程序所能開啟的檔案個數上限)決定。取兩個值中較小的值
注:使用ulimit -n 命令可以設定檔案描述符的上限
2.伺服器怎麼處理百萬連線(c10k問題)?
答:一種方法是採用乙個程序/執行緒乙個連線,但是這樣太消耗效能,另一種方法則是乙個程序/執行緒建立多個連線(io多路復用),即使用epoll技術
3.為什麼要設定tcp緩衝區?
答:① 減少系統呼叫次數(減少核心讀取次數);② 保證網路頻寬利用率
4.send/recv函式分別會在什麼時候阻塞?
答:send函式(傳送緩衝區)在buffer的允許傳送但未傳送區已滿時阻塞;而recv函式(接受緩衝區)會在已確認未讀取的資料為空時阻塞。
5.五元組指的是什麼?
答:五元分別指:網路協議、源ip、源埠、目的ip、目的埠
例:通過命令 netstat –an | grep tcp 獲取五元組
分析:從上圖可以看出,每列分別表示protocol、recv-q 、send-q、源ip:源埠、目的ip:目的埠 state,從而可以清晰的看出tcp的五元組,
6.怎樣獲取核心緩衝區的大小?
分析:從上圖可以看出,核心緩衝區為163840、tcp接收緩衝區為87380、 tcp 傳送緩衝區為16384
7.什麼是帶外資料
答:帶外資料擁有比一般資料高的優先順序,但也是通過連線傳輸資料的,tcp 是由一種叫做「緊急模式」的方法來傳輸帶外資料的,當tcp 收到乙個包含urg 標誌的資料段時,,tcp 會檢查「緊急指標」來驗證是否緊急指標所指的資料已經到達本地,然後通過psh標誌立即傳送資料。
8.listen(fd,backlog)函式的作用
答:用於獲取兩個佇列(半連線、全連線),前三次連線是在半連線佇列,之後轉入全連線,
注:檔案位置在:/proc/syn/net/ipv4/
9.為什麼不將listen和accept組合為乙個函式?
答:因為listen是非阻塞的。處理三次握手,accept負責listen處理過的連線,如果組合為乙個函式,那麼就只能是順序的三握手四揮手,沒有併發的功能了。
10. listen為什麼是非阻塞的?為什麼維護兩個連線?
答:非阻塞是因為程式設計需要,阻塞時資料有互動;兩個連線是因為要維護資料轉換過程,accept需要的時候就可以從listen中拿到,不用迴圈遍歷
11.accept為什麼是阻塞的?
答:若是非阻塞的,就要等待listen的全連線佇列、輪詢會消耗資源。所以設定accept函式為阻塞式函式。
Linux程式設計基礎 Socket程式設計
linux下的socket程式設計大體上包括tcp socket udp socket即raw socket這三種,其中tcp和udp方式的socket程式設計用於編寫應用層的socket程式,是我們用得比較多的,而raw socket則用得相對較少,不在本文介紹範圍之列。tcp socket 基於...
socket程式設計基礎
對於socket在這裡我不想究其歷史,我只想說其時它是一種程序通訊的方式,簡言之就是呼叫這個網路庫的一些api函式就能實現分布在不同主機的相關程序之間的資料交換.socket中首先我們要理解如下幾個定義概念 二是埠號 用來標識本地通訊程序,方便os提交資料.就是說程序指定了對方程序的網路ip,但這個...
socket程式設計基礎
對於socket在這裡我不想究其歷史,我只想說其時它是一種程序通訊的方式,簡言之就是呼叫這個網路庫的一些api函式就能實現分布在不同主機的相關程序之間的資料交換.socket中首先我們要理解如下幾個定義概念 二是埠號 用來標識本地通訊程序,方便os提交資料.就是說程序指定了對方程序的網路ip,但這個...