Linux基礎 socket程式設計詳解

2021-08-03 08:58:17 字數 4018 閱讀 7249

在講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,但這個...