歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux管理 >> Linux網絡 >> linux網絡編程之socket(二) C/S程序的一般流程和基本socket函數

linux網絡編程之socket(二) C/S程序的一般流程和基本socket函數

日期:2017/3/3 16:26:09   编辑:Linux網絡

一、基於TCP協議的網絡程序

下圖是基於TCP協議的客戶端/服務器程序的一般流程:

服務器調用socket()、bind() 、listen()完成初始化後,調用accept()阻塞等待,處於監聽端口的狀態,客戶端調用socket()初始化後,調用connect() 發出SYN段並阻塞等待服務器應答,服務器應答一個SYN-ACK段,客戶端收到後從connect()返回,同時應答一個ACK段,服務 器收到後從accept()返回。

數據傳輸的過程:

建立連接後,TCP協議提供全雙工的通信服務,但是一般的客 戶端/服務器程序的流程是由客戶端主動發起請求,服務器被動處理請求,一問一答的方式。因此,服務器從accept()返回 後立刻調用read(),讀socket就像讀管道一樣,如果沒有數據到達就阻塞等待,這時客戶端調用write()發送請求給服務器 ,服務器收到後從read()返回,對客戶端的請求進行處理,在此期間客戶端調用read()阻塞等待服務器的應答,服務器調用 write()將處理結果發回給客戶端,再次調用read()阻塞等待下一條請求,客戶端收到後從read()返回,發送下一條請求, 如此循環下去。

如果客戶端沒有更多的請求了,就調用close()關閉連接,就像寫端關閉的管道一樣,服務器的 read()返回0,這樣服務器就知道客戶端關閉了連接,也調用close()關閉連接。注意,任何一方調用close()後,連接的兩 個傳輸方向都關閉,不能再發送數據了。如果一方調用shutdown()則連接處於半關閉狀態,仍可接收對方發來的數據。

在學習socket API時要注意應用程序和TCP協議層是如何交互的:

*應用程序調用某個socket函數時TCP協議 層完成什麼動作,比如調用connect()會發出SYN段

*應用程序如何知道TCP協議層的狀態變化,比如從某個阻塞的 socket函數返回就表明TCP協議收到了某些段,再比如read()返回0就表明收到了FIN段

補充一下,其實TCP 共有11種 狀態,上圖沒有出現的CLOSING 狀態,當雙方同時關閉連接時會出現此狀態,替換掉FIN_WAIT2狀態。

二、基本 socket函數

1、socket函數

包含頭文件<sys/socket.h>

功能:創建一個套接字用於通信

原型: int socket(int domain, int type, int protocol);

參數

domain :指定通信協議族(protocol family),AF_INET 、AF_INET6、AF_UNIX等

type:指定socket類型,流式套接字SOCK_STREAM,數據報套接字SOCK_DGRAM,原始套接字 SOCK_RAW

protocol :協議類型,IPPROTO_TCP等;一般由前兩個參數就決定了協議類型,設置為0即可。

返回值:成 功返回非負整數, 它與文件描述符類似,我們把它稱為套接口描述字,簡稱套接字。失敗返回-1

2、bind函數

包含頭文件<sys/socket.h>

功能:綁定一個本地地址到套接字

原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

參數

sockfd:socket函數返回的套接字

addr:要綁定的地址

addrlen:地址長度

返回值:成功返回0,失敗返回-1

3、listen函數

包含頭文件 <sys/socket.h>

功能:將套接字用於監聽進入的連接

原型:int listen(int sockfd, int backlog);

參數

sockfd:socket函數返回的套接字

backlog:規定內核為此套接字排隊的最大連接個數

返回值:成功返回0,失敗 返回-1

一般來說,listen函數應該在調用socket和bind函數之後,調用函數accept之前調用。

對於給定的監聽套 接口,內核要維護兩個隊列:

1、已由客戶發出並到達服務器,服務器正在等待完成相應的TCP三路握手過程

2、已完 成連接的隊列

如下圖所示:

4、accept函數

包含頭文件 <sys/socket.h>

功能:從已完成連接隊列返回第一個連接,如果已完成連接隊列為空,則阻塞。

原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

參數

sockfd:服務器套接字

addr:將返回 對等方的套接字地址

addrlen:返回對等方的套接字地址長度

返回值:成功返回非負整數,失敗返回-1

5、 connect函數

包含頭文件<sys/socket.h>

功能:建立一個連接至addr所指定的套接字

原型:int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

參數

sockfd:未連接套接字

addr: 要連接的套接字地址

addrlen:第二個參數addr長度

返回值:成功返回0,失敗返回-1

Copyright © Linux教程網 All Rights Reserved