學習Socket編程總結

什么是Socket

Socket(套接字)是介于應用層和傳輸層之間(圖1)的應用程序編程接口。多數應用程序是由通信進程對組成,每對中的兩個進程互相發送報文,從一個進程向另一個進程發送的報文必須通過下面的網絡。進程通過Socket(套接字)軟件接口向網絡發送報文和從網絡接收報文。做個簡單的類比,進程可類比于一座房子,而它的套接字可以類比于它的門。當一個進程向位于另外一臺主機上的另一個進程發送報文時,它把報文推送出該門(套接字)。該發送進程假定該門到另外一側之間有運輸的基礎設施,該設施將把報文傳送到目的進程的門口。一旦該報文抵達目的主機,它通過進程的門(套接字)傳遞,然后接收進程對該報文進行處理。


圖1

幾種典型的Socket

1.Berkeley UNIX 操作系統定義了一種 API,稱為套接字接口(socket interface),簡稱套接字(socket)。

2.微軟公司在其操作系統中采用了套接字接口 API,形成了一個稍有不同的 API,并稱之為Windows Socket Interface,WINSOCK。

3.AT&T 為其 UNIX 系統 V 定義了一種 API,簡寫為 TLI (Transport Layer Interface)。

(本文以WINSOCK為例)

客戶端Socket API函數

TCP客戶端軟件流程

1. 確定服務器IP地址與端口號

2. 創建套接字

3. 分配本地端點地址(IP地址+端口號)(此步驟由操作系統完成)

4. 連接服務器(套接字)

5. 遵循應用層協議進行通信

6. 關閉/釋放連接

UDP客戶端軟件流程

1. 確定服務器IP地址與端口號

2. 創建套接字

3. 分配本地端點地址(IP地址+端口號)(此步驟由操作系統完成)

4. 指定服務器端點地址,構造UDP數據報

5. 遵循應用層協議進行通信

6. 關閉/釋放套接字

使用Socket的應用程序在使用Socket之前必須首先調用WSAStartup函數初始化Windows Sockets API

int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);

其中第一個參數指明程序請求使用的WinSock版本,其中高位字節指明副版本、低位字節指明主版本,第二個參數返回實際的WinSock的版本信息

int WSACleanup (void);

應用程序在完成對請求的Socket庫的使用,最后要調用WSACleanup函數解除與Socket庫的綁定,釋放Socket庫所占用的系統資源

創建socket

socket?sd = socket(protofamily,type,proto);

操作系統返回套接字描述符(sd),其中第一個參數(協議族): protofamily = PF_INET(TCP/IP),第二個參數(套接字類型):type = SOCK_STREAM,SOCK_DGRAM or SOCK_RAW(TCP/IP),第三個參數(協議號):0為默認

SOCKET sd=socket(PF_INET,SOCK_STREAM,0); (TCP)

SOCKET sd=socket(PF_INET,SOCK_DGRAM,0); (UDP)


圖2

TCP:可靠、面向連接、字節流傳輸、點對點

UDP:不可靠、無連接、數據報傳輸

int bind(sd,localaddr,addrlen);

綁定套接字的本地端點地址,IP地址+端口號,客戶程序一般不必調用bind函數

connect(sd,saddr,saddrlen);

客戶程序調用connect函數來使客戶套接字(sd)與特定計算機的特定端口(saddr)的套接字(服務)進行連接,connect函數僅用于客戶端,可用于TCP客戶端也可以用于UDP客戶端。

TCP客戶端:建立TCP連接

?UDP客戶端:指定服務器端點地址

int closesocket(SOCKET sd);

關閉一個描述符為sd的套接字,如果多個進程共享一個套接字,調用closesocket將套接字引用計數減1,減至0才關閉。如果一個進程中的多線程對一個套接字的使用無計數,當進程中的一個線程調用closesocket將一個套接字關閉,該進程中的其他線程也將不能訪問該套接字

服務端Socket API函數

服務端在創建完socket后也需要綁定本地地址,一般使用地址通配符:INADDR_ANY

int listen(sd,queuesize);

置服務器端的流套接字處于監聽狀態,僅服務器端調用面向TCP的scocket,設置連接請求隊列大小(queuesize)

newsock = accept(sd,caddr,caddrlen);

服務程序調用accept函數從處于監聽狀態的流套接字sd的客戶連接請求隊列中取出排在最前的一個客戶請求,并且創建一個新的套接字來與客戶套接字創建連接通道

send(sd,*buf,len,flags);

sendto(sd,*buf,len,flags,destaddr,addrlen);

send函數用于TCP套接字(客戶與服務器)或調用了connect函數的UDP客戶端套接字。sendto函數用于UDP服務器端套接字與未調用connect函數的UDP客戶端套接字

recv(sd,*buffer,len,flags);

recvfrom(sd,*buf,len,flags,senderaddr,saddrlen);

recv函數從TCP連接的另一端接收數據,或者從調用了connect函數的UDP客戶端套接字接收服務器發來的數據。recvfrom函數用于從UDP服務器端套接字與未調用connect函數的UDP客戶端套接字接收對端數據。

int setsockopt(int sd, int level, int optname, *optval, int optlen);

int getsockopt(int sd, int level, int optname, *optval, socklen_t *optlen);

setsockopt()函數用來設置套接字sd的選項參數。getsockopt()函數用于獲取任意類型、任意狀態套接口的選項當前值,并把結果存入optval。

網絡字節順序

1.TCP/IP定義了標準的用于協議頭中的二進制整數表示:網絡字節順序(network byte order)

2.某些Socket API函數的參數需要存儲為網絡字節順序(如IP地址、端口號等)

3.可以實現本地字節順序與網絡字節順序間轉換的函數

htons: 本地字節順序→網絡字節順序(16bits)

ntohs: 網絡字節順序→本地字節順序(16bits)

htonl: 本地字節順序→網絡字節順序(32bits)

ntohl: 網絡字節順序→本地字節順序(32bits)


網絡應用的Socket API(TCP)調用基本流程


4種類型基本服務器

1.循環無連接(Iterative connectionless)服務器

2.循環面向連接(Iterative connection-oriented)服務器

3.并發無連接(Concurrent connectionless)服務器

4.并發面向連接(Concurrent connection-oriented)服務器

循環無連接服務器基本流程

1. 創建套接字

2. 綁定端點地址(INADDR_ANY+端口號)

3. 反復接收來自客戶端的請求

4. 遵循應用層協議,構造響應報文,發送給客戶

服務器端不能使用connect()函數,無連接服務器使用sendto()函數發送數據報


調用recvfrom()函數接收數據時,自動提取客戶端點地址


循環面向連接服務器基本流程

1.創建(主)套接字,并綁定熟知端口號;

2.設置(主)套接字為被動監聽模式,準備用于服務器;

3.調用accept()函數接收下一個連接請求(通過主套接字),創建新套接字用于與該客戶建立連接;

4.遵循應用層協議,反復接收客戶請求,構造并發送響應(通過新套接字);

5.完成為特定客戶服務后,關閉與該客戶之間的連接,返回步驟3.

并發無連接服務器基本流程

主線程1: 創建套接字,并綁定熟知端口號;

主線程2: 反復調用recvfrom()函數,接收下一個 客戶請求,并創建新線程處理該客戶響應;

子線程1: 接收一個特定請求;

子線程2: 依據應用層協議構造響應報文,并調用sendto()發送;

子線程3: 退出(一個子線程處理一個請求后即終止)。

并發面向連接服務器基本流程

主線程1: 創建(主)套接字,并綁定熟知端口號;

主線程2: 設置(主)套接字為被動監聽模式,準備用于服務器;

主線程3: 反復調用accept()函數接收下一個連接請求(通過主套接字),并創建一個新 的子線程處理該客戶響應;

子線程1: 接收一個客戶的服務請求(通過新創建的套接字);

子線程2: 遵循應用層協議與特定客戶進行交互;子線程3: 關閉/釋放連接并退出(線程終止).

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 地址:http://www.cnblogs.com/taoxu/p/7064103.html 寫在準備動手的時候:...
    wvqusrtg閱讀 2,869評論 1 19
  • ———————————————回答好下面的足夠了---------------------------------...
    恒愛DE問候閱讀 1,749評論 0 4
  • 2016.9.25 好久不寫字了,第一次找到一個私密的地方。希望這里能完成我的小小夢想,嗯,我的前半生..... ...
    ATC的阿斯匹林閱讀 111評論 0 0
  • 01 前日往事,卻每日去夢 還記得畢業時每個都逃跑著離開,不敢離別不想再見。偶爾的微信群的消息,一條條的調侃一條條...
    dudo_閱讀 305評論 7 2
  • “寒窗苦讀十余載,一舉成名天下知”是廣大莘莘學子的夢想,在許多人看來,能夠進入“985”、“211”等名牌院校求學...
    藍色深晨閱讀 232評論 0 4