一 噪生、Socket
網(wǎng)絡(luò)上的兩個程序通過一個雙向的通信連接實現(xiàn)數(shù)據(jù)的交換裆赵,這個連接的一端稱為一個 Socket。Socket 又稱 "套接字"跺嗽,應(yīng)用程序通常通過 "套接字" 向網(wǎng)絡(luò)發(fā)出請求或者應(yīng)答網(wǎng)絡(luò)請求战授。
Socket 的英文原義是 “孔” 或 “插座”页藻。作為 BSD UNIX 的進(jìn)程通信機(jī)制,取后一種意思植兰。通常也稱作 "套接字"份帐,用于描述 IP 地址和端口,是一個通信鏈的句柄楣导,可以用來實現(xiàn)不同虛擬機(jī)或不同計算機(jī)之間的通信废境。在 Internet 上的主機(jī)一般運行了多個服務(wù)軟件,同時提供幾種服務(wù)筒繁。每種服務(wù)都打開一個 Socket噩凹,并綁定到一個端口上,不同的端口對應(yīng)于不同的服務(wù)毡咏。Socket 正如其英文原意那樣驮宴,像一個多孔插座。一臺主機(jī)猶如布滿各種插座的房間呕缭,每個插座有一個編號幻赚,有的插座提供 220 伏交流電,有的提供 110 伏交流電臊旭,有的則提供有線電視節(jié)目落恼。客戶軟件將插頭插到不同編號的插座离熏,就可以得到不同的服務(wù)佳谦。
Socket 就是為網(wǎng)絡(luò)服務(wù)提供的一種機(jī)制。
在 Unix中滋戳,網(wǎng)絡(luò)即是 Socket钻蔑,并不局限在 TCP/UDP。
Socket 可以用于自定義協(xié)議奸鸯。
通信的兩端都是 Socket咪笑。
網(wǎng)絡(luò)通信其實就是 Socket 間的通信。
數(shù)據(jù)在兩個 Socket 間通過 IO 傳輸娄涩。
Socket 開始是純 C 語言的窗怒,是跨平臺的。
1蓄拣、1網(wǎng)絡(luò)
1扬虚、IP 地址(主機(jī)名):
網(wǎng)絡(luò)中設(shè)備的唯一標(biāo)示。不易記憶球恤,可以用主機(jī)名(域名)辜昵。
1) IP V4:
0~255.0~255.0~255.0~255 ,共有 2\^8\^4 = 2\^32 = 42 億咽斧。
2) 本地回環(huán)地址:
每臺機(jī)器都有自己的本地回環(huán)地址堪置,ip 為 127.0.0.1 躬存,主機(jī)名為 localhost。如果 127.0.0.1 ping 不通舀锨,則網(wǎng)卡不正常岭洲。
本地 hosts 文件修改,終端:
$ cd /etc
$ sudo vim hosts
$ 輸入密碼進(jìn)入 hosts 文件編輯界面
$ 將光標(biāo)移動到指定位置
英文輸入模式下按 i 鍵進(jìn)入編輯狀態(tài)雁竞,
英文輸入模式下按 esc 鍵進(jìn)入命令狀態(tài),
在命令狀態(tài)下輸入 :wq 回車拧额,保存退出 hosts 文件碑诉。
2、端口號:
用于標(biāo)示進(jìn)程的邏輯地址侥锦,不同進(jìn)程的標(biāo)示进栽。
有效端口為 0 ~ 65535,其中 0 ~ 1024 由系統(tǒng)使用或者保留端口恭垦,開發(fā)中不要使用 1024 以下的端口快毛。
1) Netcat 的使用:
Netcat 是 Mac 終端下用于調(diào)試和檢查網(wǎng)絡(luò)的工具包,可用于創(chuàng)建 TCP/IP 連接番挺。
終端:$ nc -lk 12345唠帝,開啟監(jiān)聽,終端將始終監(jiān)聽本地計算機(jī) 12345 端口的數(shù)據(jù)玄柏。
3襟衰、傳輸協(xié)議(通訊的規(guī)則):
1) TCP:傳輸控制協(xié)議:
建立連接,形成傳輸數(shù)據(jù)的通道(建立連接的三次握手粪摘,斷開連接的四次握手)瀑晒。
在連接中進(jìn)行大數(shù)據(jù)傳輸,數(shù)據(jù)大小不收限制徘意。
通過三次握手完成連接苔悦,是可靠協(xié)議,數(shù)據(jù)安全送達(dá)椎咧。
必須建立連接玖详,效率會稍低。
2) UDP:用戶數(shù)據(jù)報協(xié)議:
只管發(fā)送勤讽,不確認(rèn)對方是否接收到竹宋。
不需要建立連接,將數(shù)據(jù)及源和目的封裝成數(shù)據(jù)包中地技,每個數(shù)據(jù)報的大小限制在 64K 之內(nèi)蜈七。
因為無需連接,因此是不可靠協(xié)議莫矗。
不需要建立連接飒硅,速度快砂缩。
應(yīng)用場景:多媒體教室/網(wǎng)絡(luò)流媒體。
3) 常見網(wǎng)絡(luò)協(xié)議:
4三娩、網(wǎng)絡(luò)參考模型:
1庵芭、2 ? Socket通訊示意圖
1、3 Socket連接過程
根據(jù)連接啟動的方式以及本地套接字要連接的目標(biāo)雀监,套接字之間的連接過程可以分為三個步驟:服務(wù)器監(jiān)聽双吆,客戶端請求,連接確認(rèn)会前。
1) 服務(wù)器監(jiān)聽:
是服務(wù)器端套接字并不定位具體的客戶端套接字好乐,而是處于等待連接的狀態(tài),實時監(jiān)控網(wǎng)絡(luò)狀態(tài)瓦宜。
2) 客戶端請求:
是指由客戶端的套接字提出連接請求蔚万,要連接的目標(biāo)是服務(wù)器端的套接字。為此临庇,客戶端的套接字必須首先描述它要連接的服務(wù)器的套接字反璃,指出服務(wù)器端套接字的地址和端口號,然后就向服務(wù)器端套接字提出連接請求假夺。
3) 連接確認(rèn):
是指當(dāng)服務(wù)器端套接字監(jiān)聽到或者說接收到客戶端套接字的連接請求淮蜈,它就響應(yīng)客戶端套接字的請求,建立一個新的線程已卷,把服務(wù)器端套接字的描述發(fā)給客戶端礁芦,一旦客戶端確認(rèn)了此描述,連接就建立好了悼尾。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽狀態(tài)柿扣,繼續(xù)接收其他客戶端套接字的連接請求。
1闺魏、4 Socket常用函數(shù)
1) 創(chuàng)建:
函數(shù)原型:
int socket(int domain, int type, int protocol);
參數(shù)說明:
domain:協(xié)議域未状,又稱協(xié)議族(family)。常用的協(xié)議族有 AF_INET(ipv4)析桥、
AF_INET6(ipv6)司草、
AF_LOCAL(或稱 AF_UNIX,Unix 域 Socket)泡仗、
AF_ROUTE 等埋虹。
協(xié)議族決定了 socket 的地址類型,在通信中必須采用對應(yīng)的地址娩怎,如 AF_INET 決定了要用 ipv4 地址(32 位的)與端口號(16 位的)的組合搔课、AF_UNIX 決定了要用一個絕對路徑名作為地址。
type:指定 Socket 類型截亦。常用的 socket 類型有 SOCK_STREAM(流式/TCP)爬泥、
SOCK_DGRAM(數(shù)據(jù)報式/UDP)柬讨、
SOCK_RAW、
SOCK_PACKET袍啡、
SOCK_SEQPACKET 等踩官。
流式 Socket(SOCK_STREAM)是一種面向連接的 Socket,針對于面向連接的 TCP 服務(wù)應(yīng)用境输。數(shù)據(jù)報式
Socket(SOCK_DGRAM)是一種無連接的 Socket蔗牡,對應(yīng)于無連接的 UDP 服務(wù)應(yīng)用。
protocol:指定協(xié)議嗅剖。常用協(xié)議有 IPPROTO_TCP(TCP 傳輸協(xié)議)辩越、
IPPROTO_UDP(UDP 傳輸協(xié)議)、
IPPROTO_STCP(STCP 傳輸協(xié)議)窗悯、
IPPROTO_TIPC(TIPC 傳輸協(xié)議)等区匣,
注意:
1. type 和 protocol 不可以隨意組合偷拔,如 SOCK_STREAM 不可以跟 IPPROTO_UDP 組合蒋院。當(dāng)?shù)谌齻€參數(shù)為 0 時,會自動選擇第二個參數(shù)類型對應(yīng)的默認(rèn)協(xié)議莲绰。
2. Windows Socket 下 protocol 參數(shù)中不存在 IPPROTO_STCP欺旧。
返回值:
如果調(diào)用成功就返回新創(chuàng)建的套接字的描述符,如果失敗就返INVALID_SOCKET(Linux 下失敗返回 -1)蛤签。套接字描述符是一個整數(shù)類型的值辞友。每個進(jìn)程的進(jìn)程空間里都有一個套接字描述符表,該表中存放著套接字描述符和套接字?jǐn)?shù)據(jù)結(jié)構(gòu)的對應(yīng)關(guān)系震肮。該表中有一個字段存放新創(chuàng)建的套接字的描述符称龙,另一個字段存放套接字?jǐn)?shù)據(jù)結(jié)構(gòu)的地址,因此根據(jù)套接字描述符就可以找到其對應(yīng)的套接字?jǐn)?shù)據(jù)結(jié)構(gòu)戳晌。每個進(jìn)程在自己的進(jìn)程空間里都有一個套接字描述符表但是套接字?jǐn)?shù)據(jù)結(jié)構(gòu)都是在操作系統(tǒng)的內(nèi)核緩沖里鲫尊。
2) 綁定:
函數(shù)原型:
int bind(SOCKET socket, const struct sockaddr* address, socklen_t address_len);
參數(shù)說明:
socket:是一個套接字描述符。
address:是一個 sockaddr 結(jié)構(gòu)指針沦偎,該結(jié)構(gòu)中包含了要結(jié)合的地址和端口號疫向。
address_len:確定 address 緩沖區(qū)的長度。
返回值:
如果函數(shù)執(zhí)行成功豪嚎,返回值為 0搔驼,否則為 SOCKET_ERROR。
3) 接收:
函數(shù)原型:
int recv(SOCKET socket, char FAR* buf, int len, int flags);
參數(shù)說明:
socket:一個標(biāo)識已連接套接口的描述字侈询。
buf:用于接收數(shù)據(jù)的緩沖區(qū)舌涨。
len:緩沖區(qū)長度。
flags:指定調(diào)用方式扔字。取值:MSG_PEEK 查看當(dāng)前數(shù)據(jù)泼菌,數(shù)據(jù)將被復(fù)制到緩沖區(qū)中谍肤,但并不從輸入隊列中刪除;MSG_OOB 指示接收到 out-of-band 數(shù)據(jù)(即需要優(yōu)先處理的數(shù)據(jù))哗伯。
返回值:
若無錯誤發(fā)生荒揣,recv() 返回讀入的字節(jié)數(shù)。如果連接已中止焊刹,返回 0系任。否則的話,返回 SOCKET_ERROR 錯誤虐块,應(yīng)用程序可通過 WSAGetLastError() 獲取相應(yīng)錯誤代碼俩滥。
函數(shù)原型:
ssize_t recvfrom(int sockfd, void buf, int len, unsigned int flags, struct socketaddr* from, socket_t* fromlen);
參數(shù)說明:
sockfd:標(biāo)識一個已連接套接口的描述字。
buf:接收數(shù)據(jù)緩沖區(qū)贺奠。
len:緩沖區(qū)長度霜旧。
flags:調(diào)用操作方式。是以下一個或者多個標(biāo)志的組合體儡率,可通過 or 操作連在一起:
(1)MSG_DONTWAIT:操作不會被阻塞挂据;
(2)MSG_ERRQUEUE:指示應(yīng)該從套接字的錯誤隊列上接收錯誤值,依據(jù)不同的協(xié)議儿普,錯誤值以某種輔佐性消息的方式傳遞進(jìn)來崎逃,使用者應(yīng)該提供足夠大的緩沖區(qū)。導(dǎo)致錯誤的原封包通過 msg_iovec 作為一般的數(shù)據(jù)來傳遞眉孩。導(dǎo)致錯誤的數(shù)據(jù)報原目標(biāo)地址作為 msg_name 被提供个绍。錯誤以 sock_extended_err結(jié)構(gòu)形態(tài)被使用。
(3)MSG_PEEK:指示數(shù)據(jù)接收后浪汪,在接收隊列中保留原數(shù)據(jù)巴柿,不將其刪除,隨后的讀操作還可以接收相同的數(shù)據(jù)死遭。
(4)MSG_TRUNC:返回封包的實際長度广恢,即使它比所提供的緩沖區(qū)更長, 只對 packet 套接字有效殃姓。
(5)MSG_WAITALL:要求阻塞操作袁波,直到請求得到完整的滿足。然而蜗侈,如果捕捉到信號篷牌,錯誤或者連接斷開發(fā)生,或者下次被接收的數(shù)據(jù)類型不同踏幻,仍會返回少于請求量的數(shù)據(jù)枷颊。
(6)MSG_EOR:指示記錄的結(jié)束,返回的數(shù)據(jù)完成一個記錄。
(7)MSG_CTRUNC:指明由于緩沖區(qū)空間不足夭苗,一些控制數(shù)據(jù)已被丟棄信卡。
(8)MSG_OOB:指示接收到 out-of-band 數(shù)據(jù)(即需要優(yōu)先處理的數(shù)據(jù))。
(9)MSG_ERRQUEUE:指示除了來自套接字錯誤隊列的錯誤外题造,沒有接收到其它數(shù)據(jù)傍菇。
from:(可選)指針,指向裝有源地址的緩沖區(qū)界赔。
fromlen:(可選)指針丢习,指向from緩沖區(qū)長度值。
4) 發(fā)送:
函數(shù)原型:
int sendto(SOCKET s, const char FAR* buf, int size, int flags, const struct sockaddr FAR* to, int tolen);
參數(shù)說明:
s:套接字
buf:待發(fā)送數(shù)據(jù)的緩沖區(qū)
size:緩沖區(qū)長度
flags:調(diào)用方式標(biāo)志位, 一般為 0, 改變 Flags淮悼,將會改變 Sendto 發(fā)送的形式
addr:(可選)指針咐低,指向目的套接字的地址
tolen:addr 所指地址的長度
返回值:
如果成功,則返回發(fā)送的字節(jié)數(shù)袜腥,失敗則返回 SOCKET_ERROR见擦。
5) 接收連接請求:
函數(shù)原型:
int accept(int fd, struct socketaddr* addr, socklen_t* len);
參數(shù)說明:
fd:套接字描述符。
addr:返回連接著的地址
len:接收返回地址的緩沖區(qū)長度
返回值:
成功返回客戶端的文件描述符羹令,失敗返回 -1鲤屡。
二、Socket的基本使用
Objective-C
包含頭文件 ??
創(chuàng)建 Socket
連接到服務(wù)器
發(fā)送數(shù)據(jù)
接收數(shù)據(jù)
關(guān)閉連接
三特恬、Socket聊天
Objective-C
四执俩、Socket網(wǎng)絡(luò)訪問
請求:
1徐钠、請求行
GET / HTTP/1.1
方法 GET
路徑 /
協(xié)議 HTTP 1.1
2癌刽、請求頭
Host: localhost 主機(jī)
User-Agent: 告訴服務(wù)器客戶端的類型
Accept: 告訴服務(wù)器客戶端支持的格式
Accept-Language: 告訴服務(wù)器客戶端的語言
Accept-Encoding: 告訴服務(wù)器客戶端支持的壓縮格式
響應(yīng):
1、狀態(tài)行
HTTP/1.1 200 OK
協(xié)議 HTTP 1.1
狀態(tài)碼:
200 成功
404 頁面沒找到
301 內(nèi)容沒變化尝丐,用在緩存
2显拜、響應(yīng)頭(主要在開發(fā)下載應(yīng)用的時候使用的)
Date: Tue, 24 Mar 2015 01:52:25 GMT 訪問日期
Server: Apache/2.4.9 (Unix) 訪問服務(wù)器的類型
Content-Location: index.html.en 訪問的文件名
Content-Length: 45 訪問文件的大小
Content-Type: text/html 訪問文件的類型
3、數(shù)據(jù)實體
訪問服務(wù)器最需的爹袁,相當(dāng)于 NSURLConnection 異步方法回調(diào)中的 data远荠。
Objective-C