三.命名套接字
之前的socket只是創建了一個沒有名字的資源,其他進程無法訪問他.所以也無法從它接受消息.只有當bind給套接字綁定了端口和名字后,其他進程才能找到它.
一般服務器是一定要bind,但是客戶端就不一定了.如果做一個簡單的echo服務器的話,那么客戶端只直接去connect服務器就可以了.
綁定函數int bind(int socket,const struct sockaddr *address,socklen_t address_len);
socket就是socket函數返回的描述字.第二個參數是通用接口!所以如果你的地址結構體用的不是這個,那么一定要有強制轉換!!第三個參數是未轉換前的地址結構體的大小+1.
返回值0為正常,-1則設置errno表示出錯.
綁定之后,就是connect和listen了.開始區分客戶端和服務端了.
四.套接字通信模式
首先,通信模式分為兩種,TCP和UDP.
前者面向連接,后者則以報文形式發送.
下圖是TCP的編程過程.
這是UDP的編程過程.
看完了編程模式,現在再來看具體函數是怎么執行的吧~
五.流套接字操作
1.connect
原型int connect (int socket,const struct sockaddr *address,socklen_t address_len);
首先這個是用於客戶端的.這里的socket就是本地的socket描述字,address是服務器端的地址信息.最后的address_len為其原先地址的長度.
返回值0為正常,錯誤返回-1,並設置errno,錯誤條件有:
EBADD: 參數socket不是合法的套接字描述字
EALREADY: 已經有一懸掛的連接正在被處理
ETIMEDOUT: 建立連接的時間限已過而未能建立連接.
ECONNREFUSED: 服務端拒絕此連接.
EINTR: 建立連接的企圖被捕獲的信號所中斷
這個連接產生問題的情況比較多,我寫的細一點:
正常情況下連接肯定是正常的.如果連接超時,則返回並流產連接請求.
如果connect在連接過程中被信號中斷,那么雖然也錯誤返回.但是請求並不流產.連接會被異步建立.
如果建立套接字的時候設置了O_NONBLOCK的話,如果不能被立即建立的話,那么也會和被中斷的時候一樣,連接異步的建立.
針對這種異步的情況,可以用select或者poll來查詢連接是否就緒.
2.listen
原型int listen(int socket,int backlog);
函數會為第一個參數建立一個連接請求的偵聽隊列,然后這個隊列就會成為一個服務器套接字,也叫被動套接字.第二個參數則是用來設置其隊列的最大長度的.如果設置的值大於系統規定的最大限制值時,這種情況下,當偵聽隊列的連接請求超過系統的限制值時,系統會自動的截斷backlog的值為系統最大值.如果設置為小於0,則自動設置為0
當返回值為0時表示成功,失敗則返回-1並設置errno.
注意這個不能用於無連接風格的套接字!