最近系統的看了下unix網路程式設計的一些內容,對socket的理解有了進一步的加深,在看apue的時候,那會兒看socket上面介紹的比較少,只是模糊的懂了如何去寫乙個簡單的tcp服務端和客戶端,對其中一些注意的點,以及實現的原理沒有過多的去研究。這是我自己總結的socket程式設計的第一篇,基本就是介紹一些基礎性的東西。
這個只是在ipv4上的一些socket程式設計,對於ipv6暫不涉及。下面對unix網路程式設計卷一第三版簡稱為unpv13e
提到位址結構我們一般使用的是最基本的位址結構。ipv4的位址結構為struct sockaddr_in
裡面包含了一些字段。如sin_family, sin_addr, sin_port
.對於sin_addr
這是乙個結構體型別的。宣告是struct in_addr
.struct sockaddr_in
是定義在中的。而對於結構體中所 涉及到的變數的定義一般包含在
,
. 所以一般在程式設計的時候需要注意將這些標頭檔案引用。
上述詳細的討論可以參看unpv13e的p56-p57
。裡面的討論比較詳盡。
接著我們還有一類位址結構,稱作通用位址結構。這是位址結構的引入是為了對各種socket的位址結構做乙個統一的,通用位址的定義是struct sockaddr
捨去了字尾。這個位址結構的使用我們一般是用在型別強轉上面。例如bind
函式第二個引數需要強轉為struct sockaddr
遵循richard的思想,將struct sockaddr精簡一下,使用define將其定義為sa. 如此便省去敲擊的次數。
最後還有一類更加通用的位址結構,稱作新的通用位址結構
. 它比之前的位址結構更具通用性,能夠儲存任意大小的結構體。struct sockaddr_storage
這個結構一部分是對使用者透明的。所以使用的時候我們一般不需要擔心空間不夠。
不同的機器上,使用的位元組序一般是不同的,一般稱作大端和小端。我們為什麼要討論這個問題呢?因為作為網路程式設計,雙方之間的通訊要一致。比如我這邊是使用的小端,而對方機器是大端,那麼解析後的結果就是錯亂的,因此我們需要做的就是將其統一起來。需要乙個能夠將本地轉為網路位元組,再從網路位元組轉為本地,這之間的細節包括網路位元組轉本地的時候需要對機器進行大小端的判斷。這樣就避免了錯亂。我們自己如何來判斷乙個機器的大小端呢?
我們使用的是聯合這個資料型別來實現的。具體的實現參看我的gits,一般linux上使用的是小端位元組序。
討論了位元組序後我們需要知道的是如何將本地和網路位元組序進行互換,一般提供了一些介面,我們一一來簡單的討論下。
tcp中一般是16位的埠號和32位的ipv4位址。而我們在實現本地轉網路的時候不需要去考慮本地是大端還是小端了,只需要考慮需要轉的內容長度了。因為從如下的四個函式可以看出htons
,htonl
,ntohs
,ntohl
這邊的n代表network,h代表host, l代表long,s代表short。我們把l視為32位的,將s視為16位的。這樣在轉換ip和port的時候就很方便了。但是需要注意的就是我們在使用這些函式的時候需要注意的就是我們的引數是整型的,這一點需要注意到。
對乙個結構體進行初始化,或是陣列初始話的時候我們要做的就是使用一些位元組操縱函式來實現。一般我們會想到使用memset
這個函式,同樣在linux中有另外一組不錯的函式,是bsd所提供的,稱作bzero
bcmp
bcopy
以位元組來實現相關的操作,而不是以c語言中string的這個概念中所做的那樣。
使用bzero在網路程式設計中是又好處的。因為引數少,直接將目標初始化成0. 而memset多乙個引數。還有一點就是memset無法處理位元組重疊的這個問題。而bzero是可以解決的。這一塊使用bzero可以省去一些麻煩。這個函式是包含在這個標頭檔案中的。而memset是包含在
中的。
一般我們的輸入都是基於字串這個格式的,使用的比較多,所以如果提供乙個直接將字串格式的位址或是埠轉換成網路位元組序的函式的話,那麼我們就會變得更加的方便。
這邊也有兩組不一樣的函式,一般我們傾向使用後面一組。 好了先說說第一組的函式。
這組函式用起來還是可以的。不過更流行的使用是使用下面的這兩個。
不過為了防止錯誤,在中有乙個好的定義,為
inet_addrstrlen
大小定義為16,這就保證了我們的大小不會溢位。
上面的兩組函式都包含在這個標頭檔案中。
但是下面的那兩個函式有乙個不太好的就是我們要確定sock的型別,而不是直接傳入乙個位址結構,所以richard給出了這樣的乙個封裝函式,處理起來應該就是比較輕鬆一些。
char *sock_ntop(const sockaddr *sa, socklen_t salen)return
str;}}
}
另外還有其他幾個函式,實現都可以在源**中找到。因為這些函式比較好的乙個點就是我們呼叫的時候省去了很多的細節。
socket的一部分內容基本上是介紹完了。在位元組流套接字上,read和write是不同於檔案的i/o的。所以還有一套不錯的函式
socket程式設計基礎
對於socket在這裡我不想究其歷史,我只想說其時它是一種程序通訊的方式,簡言之就是呼叫這個網路庫的一些api函式就能實現分布在不同主機的相關程序之間的資料交換.socket中首先我們要理解如下幾個定義概念 二是埠號 用來標識本地通訊程序,方便os提交資料.就是說程序指定了對方程序的網路ip,但這個...
socket程式設計基礎
對於socket在這裡我不想究其歷史,我只想說其時它是一種程序通訊的方式,簡言之就是呼叫這個網路庫的一些api函式就能實現分布在不同主機的相關程序之間的資料交換.socket中首先我們要理解如下幾個定義概念 二是埠號 用來標識本地通訊程序,方便os提交資料.就是說程序指定了對方程序的網路ip,但這個...
Go基礎程式設計 Socket程式設計
socket起源於unix,而unix基本哲學之一就是 一切皆檔案 都可以用 開啟open 讀寫write read 關閉close 模式來操作。socket就是該模式的乙個實現,網路的socket資料傳輸是一種特殊的i o,socket也是一種檔案描述符。socket也具有乙個類似於開啟檔案的函式...