網路伺服器開發實戰(3) Socket程式設計基礎

2021-09-08 23:15:43 字數 2591 閱讀 2079

在linux下,socket用整型int表示,套接字控制代碼和檔案控制代碼都是int,因為socket是用於程序間網路通訊的特殊檔案型別,本質為核心借助緩衝區形成的偽檔案,即我們可以把它當作乙個檔案來用

因為linux的設計是「一切皆檔案」,為了統一介面,方便程式設計,比如管道,程序,執行緒,裝置驅動都定義為檔案

讀寫套接字和讀寫檔案一致,如呼叫read和write方法

區別是:檔案主要用於本地持久化資料的讀寫;套接字用於網路程序間資料的傳遞

在tcp/ip協議中,ip位址+埠號來唯一標識網路通訊中的乙個程序,「ip位址(32位)+埠號(16位)」就對應乙個socket,要建立連線,兩個程序各自都會有兩個socket來標識,兩個socket組成的socket pair就唯一標識乙個連線

在網路通訊中,套接字一定是成對出現的,一端的傳送緩衝區對應對端的接收緩衝區,我們使用同乙個檔案描述符來操作傳送緩衝區和接收緩衝區

參考上篇部落格的回聲伺服器端與客戶端的實現

此處讀寫可以同時進行,為全雙工通訊

同時讀寫可以採用同步和非同步兩種方式實現

同步:同步+多執行緒實現同時讀寫

非同步:乙個程序或執行緒就可以實現同時讀寫

在計算機組成原理這門課中,我們知道記憶體中資料存放有大端和小端兩種順序

這種順序的記憶,可以根據低位位元組存放的位置來記憶

磁碟檔案中的多位元組資料相對於檔案中的偏移位址也有大端小端之分,網路資料流同樣有大端小端之分

<1>傳送和接收順序

傳送主機通常將傳送緩衝區中的資料按記憶體位址從低到高的順序發出,

接收主機把從網路上接到的位元組依次儲存在接收緩衝區中,也是按記憶體位址從低到高的順序儲存

<2>tcp/ip協議規定,網路資料流應採用大端位元組序,即低位址高位元組

<3>例項

埠號是1001(0x3e9),由兩個位元組儲存,

採用大端位元組序,則低位址是0x03,高位址是0xe9,也就是先發0x03,再發0xe9,

這16位在傳送主機的緩衝區中也應該是低位址存0x03,高位址存0xe9。

1)如果傳送主機是小端位元組序的,這16位被解釋成0xe903,而不是1001。因此,傳送主機把1001填到傳送緩衝區之前需要做位元組序的轉換。同樣地,接收主機如果是小端位元組序的,接到16位的源埠號也要做位元組序的轉換。

2)如果主機是大端位元組序的,傳送和接收都不需要做轉換。同理,32位的ip位址也要考慮網路位元組序和主機位元組序的問題。

為使網路程式具有可移植性,使同樣的c**在大端和小端計算機上編譯後都能正常執行,可以呼叫以下庫函式做網路位元組序和主機位元組序的轉換

#include uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);

//h表示host,n表示network,l表示32位長整數,s表示16位短整數。

//如果主機是小端位元組序,這些函式將引數做相應的大小端轉換然後返回,如果主機是大端位元組序,這些函式不做轉換,將引數原封不動地返回。

為什麼在前面寫的回聲伺服器中,在函式呼叫時要將sockaddr_in型變數強制轉換成sockaddr呢?

很多網路程式設計函式誕生早於ipv4協議,那時候都使用的是sockaddr結構體,為了向前相容,現在sockaddr退化成了(void *)的作用,傳遞乙個位址給函式,至於這個位址是sockaddr_in(ipv4)還是其他的,由位址族確定,然後函式內部再強制型別轉化為所需的位址型別。

struct in_addr ; //32位的網路位元組順序的ip位址,是乙個32位的無符號整型數

//比如說要顯示ip位址,這個就要轉成字串;要接收使用者輸入的字串,就要轉成整型數,可以用ip位址轉換函式來處理

ipv4的位址格式定義在netinet/in.h中,

ipv4位址用sockaddr_in結構體表示,包括16位埠號和32位ip位址,但是sock api的實現早於ansi c標準化,那時還沒有void *型別,因此這些像bind 、accept函式的引數都用struct sockaddr *型別表示,在傳遞引數之前要強制型別轉換一下,

例如:

struct sockaddr_in servaddr;

bind(listen_fd, (struct sockaddr *)&servaddr, sizeof(servaddr)); /* initialize servaddr */

網路伺服器開發實戰練習( ) 回聲伺服器實現

實現回聲伺服器的客戶端伺服器程式,客戶端通過網路連線到伺服器,並傳送任意一串英文資訊,伺服器端接受資訊後,將每個字元轉換為大寫並回送給客戶端顯示。本示例來自於動腦學院 artin老師的免費課程 例子 90年代的通訊 寄信者 寫好要傳送的位址 還要寫好相應的姓名,因為接受位址有很多人,到底屬於誰接收就...

關於網路伺服器

假如我有數千萬甚至是上億的使用者資料,我想把使用者自增id和使用者名稱username放到快取裡。我的需求是,當要查詢使用者的資訊時,我想先從快取裡根據使用者名稱username獲取到使用者的id,然後再通過id在資料庫裡查詢使用者的資訊。我想當乙個使用者表達到上億的數量級別時,用自增id來查詢肯定...

網路伺服器宕機

1.伺服器程序終止 當伺服器程序終止時,伺服器傳送fin給客戶端,客戶端回以ack,客戶端進入close wait狀態,但還沒有結束連線。此時客戶端阻塞於fgets,客戶端繼續傳送buffer,伺服器傳送rst,客戶端readline返回0。而如果客戶端不理睬readline返回的rst,繼續wri...