一 、Socket
網絡上的兩個程序通過一個雙向的通信連接實現數據的交換,這個連接的一端稱為一個 Socket。Socket 又稱 "套接字",應用程序通常通過 "套接字" 向網絡發出請求或者應答網絡請求。
Socket 的英文原義是 “孔” 或 “插座”。作為 BSD UNIX 的進程通信機制,取后一種意思。通常也稱作 "套接字",用于描述 IP 地址和端口,是一個通信鏈的句柄,可以用來實現不同虛擬機或不同計算機之間的通信。在 Internet 上的主機一般運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個 Socket,并綁定到一個端口上,不同的端口對應于不同的服務。Socket 正如其英文原意那樣,像一個多孔插座。一臺主機猶如布滿各種插座的房間,每個插座有一個編號,有的插座提供 220 伏交流電,有的提供 110 伏交流電,有的則提供有線電視節目。客戶軟件將插頭插到不同編號的插座,就可以得到不同的服務。
Socket 就是為網絡服務提供的一種機制。
在 Unix中,網絡即是 Socket,并不局限在 TCP/UDP。
Socket 可以用于自定義協議。
通信的兩端都是 Socket。
網絡通信其實就是 Socket 間的通信。
數據在兩個 Socket 間通過 IO 傳輸。
Socket 開始是純 C 語言的,是跨平臺的。
1、1網絡
1、IP 地址(主機名):
網絡中設備的唯一標示。不易記憶,可以用主機名(域名)。
1) IP V4:
0~255.0~255.0~255.0~255 ,共有 2\^8\^4 = 2\^32 = 42 億。
2) 本地回環地址:
每臺機器都有自己的本地回環地址,ip 為 127.0.0.1 ,主機名為 localhost。如果 127.0.0.1 ping 不通,則網卡不正常。
本地 hosts 文件修改,終端:
$ cd /etc
$ sudo vim hosts
$ 輸入密碼進入 hosts 文件編輯界面
$ 將光標移動到指定位置
英文輸入模式下按 i 鍵進入編輯狀態,
英文輸入模式下按 esc 鍵進入命令狀態,
在命令狀態下輸入 :wq 回車,保存退出 hosts 文件。
2、端口號:
用于標示進程的邏輯地址,不同進程的標示。
有效端口為 0 ~ 65535,其中 0 ~ 1024 由系統使用或者保留端口,開發中不要使用 1024 以下的端口。
1) Netcat 的使用:
Netcat 是 Mac 終端下用于調試和檢查網絡的工具包,可用于創建 TCP/IP 連接。
終端:$ nc -lk 12345,開啟監聽,終端將始終監聽本地計算機 12345 端口的數據。
3、傳輸協議(通訊的規則):
1) TCP:傳輸控制協議:
建立連接,形成傳輸數據的通道(建立連接的三次握手,斷開連接的四次握手)。
在連接中進行大數據傳輸,數據大小不收限制。
通過三次握手完成連接,是可靠協議,數據安全送達。
必須建立連接,效率會稍低。
2) UDP:用戶數據報協議:
只管發送,不確認對方是否接收到。
不需要建立連接,將數據及源和目的封裝成數據包中,每個數據報的大小限制在 64K 之內。
因為無需連接,因此是不可靠協議。
不需要建立連接,速度快。
應用場景:多媒體教室/網絡流媒體。
3) 常見網絡協議:
4、網絡參考模型:
1、2 ? Socket通訊示意圖
1、3 Socket連接過程
根據連接啟動的方式以及本地套接字要連接的目標,套接字之間的連接過程可以分為三個步驟:服務器監聽,客戶端請求,連接確認。
1) 服務器監聽:
是服務器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態,實時監控網絡狀態。
2) 客戶端請求:
是指由客戶端的套接字提出連接請求,要連接的目標是服務器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務器的套接字,指出服務器端套接字的地址和端口號,然后就向服務器端套接字提出連接請求。
3) 連接確認:
是指當服務器端套接字監聽到或者說接收到客戶端套接字的連接請求,它就響應客戶端套接字的請求,建立一個新的線程,把服務器端套接字的描述發給客戶端,一旦客戶端確認了此描述,連接就建立好了。而服務器端套接字繼續處于監聽狀態,繼續接收其他客戶端套接字的連接請求。
1、4 Socket常用函數
1) 創建:
函數原型:
int socket(int domain, int type, int protocol);
參數說明:
domain:協議域,又稱協議族(family)。常用的協議族有 AF_INET(ipv4)、
AF_INET6(ipv6)、
AF_LOCAL(或稱 AF_UNIX,Unix 域 Socket)、
AF_ROUTE 等。
協議族決定了 socket 的地址類型,在通信中必須采用對應的地址,如 AF_INET 決定了要用 ipv4 地址(32 位的)與端口號(16 位的)的組合、AF_UNIX 決定了要用一個絕對路徑名作為地址。
type:指定 Socket 類型。常用的 socket 類型有 SOCK_STREAM(流式/TCP)、
SOCK_DGRAM(數據報式/UDP)、
SOCK_RAW、
SOCK_PACKET、
SOCK_SEQPACKET 等。
流式 Socket(SOCK_STREAM)是一種面向連接的 Socket,針對于面向連接的 TCP 服務應用。數據報式
Socket(SOCK_DGRAM)是一種無連接的 Socket,對應于無連接的 UDP 服務應用。
protocol:指定協議。常用協議有 IPPROTO_TCP(TCP 傳輸協議)、
IPPROTO_UDP(UDP 傳輸協議)、
IPPROTO_STCP(STCP 傳輸協議)、
IPPROTO_TIPC(TIPC 傳輸協議)等,
注意:
1. type 和 protocol 不可以隨意組合,如 SOCK_STREAM 不可以跟 IPPROTO_UDP 組合。當第三個參數為 0 時,會自動選擇第二個參數類型對應的默認協議。
2. Windows Socket 下 protocol 參數中不存在 IPPROTO_STCP。
返回值:
如果調用成功就返回新創建的套接字的描述符,如果失敗就返INVALID_SOCKET(Linux 下失敗返回 -1)。套接字描述符是一個整數類型的值。每個進程的進程空間里都有一個套接字描述符表,該表中存放著套接字描述符和套接字數據結構的對應關系。該表中有一個字段存放新創建的套接字的描述符,另一個字段存放套接字數據結構的地址,因此根據套接字描述符就可以找到其對應的套接字數據結構。每個進程在自己的進程空間里都有一個套接字描述符表但是套接字數據結構都是在操作系統的內核緩沖里。
2) 綁定:
函數原型:
int bind(SOCKET socket, const struct sockaddr* address, socklen_t address_len);
參數說明:
socket:是一個套接字描述符。
address:是一個 sockaddr 結構指針,該結構中包含了要結合的地址和端口號。
address_len:確定 address 緩沖區的長度。
返回值:
如果函數執行成功,返回值為 0,否則為 SOCKET_ERROR。
3) 接收:
函數原型:
int recv(SOCKET socket, char FAR* buf, int len, int flags);
參數說明:
socket:一個標識已連接套接口的描述字。
buf:用于接收數據的緩沖區。
len:緩沖區長度。
flags:指定調用方式。取值:MSG_PEEK 查看當前數據,數據將被復制到緩沖區中,但并不從輸入隊列中刪除;MSG_OOB 指示接收到 out-of-band 數據(即需要優先處理的數據)。
返回值:
若無錯誤發生,recv() 返回讀入的字節數。如果連接已中止,返回 0。否則的話,返回 SOCKET_ERROR 錯誤,應用程序可通過 WSAGetLastError() 獲取相應錯誤代碼。
函數原型:
ssize_t recvfrom(int sockfd, void buf, int len, unsigned int flags, struct socketaddr* from, socket_t* fromlen);
參數說明:
sockfd:標識一個已連接套接口的描述字。
buf:接收數據緩沖區。
len:緩沖區長度。
flags:調用操作方式。是以下一個或者多個標志的組合體,可通過 or 操作連在一起:
(1)MSG_DONTWAIT:操作不會被阻塞;
(2)MSG_ERRQUEUE:指示應該從套接字的錯誤隊列上接收錯誤值,依據不同的協議,錯誤值以某種輔佐性消息的方式傳遞進來,使用者應該提供足夠大的緩沖區。導致錯誤的原封包通過 msg_iovec 作為一般的數據來傳遞。導致錯誤的數據報原目標地址作為 msg_name 被提供。錯誤以 sock_extended_err結構形態被使用。
(3)MSG_PEEK:指示數據接收后,在接收隊列中保留原數據,不將其刪除,隨后的讀操作還可以接收相同的數據。
(4)MSG_TRUNC:返回封包的實際長度,即使它比所提供的緩沖區更長, 只對 packet 套接字有效。
(5)MSG_WAITALL:要求阻塞操作,直到請求得到完整的滿足。然而,如果捕捉到信號,錯誤或者連接斷開發生,或者下次被接收的數據類型不同,仍會返回少于請求量的數據。
(6)MSG_EOR:指示記錄的結束,返回的數據完成一個記錄。
(7)MSG_CTRUNC:指明由于緩沖區空間不足,一些控制數據已被丟棄。
(8)MSG_OOB:指示接收到 out-of-band 數據(即需要優先處理的數據)。
(9)MSG_ERRQUEUE:指示除了來自套接字錯誤隊列的錯誤外,沒有接收到其它數據。
from:(可選)指針,指向裝有源地址的緩沖區。
fromlen:(可選)指針,指向from緩沖區長度值。
4) 發送:
函數原型:
int sendto(SOCKET s, const char FAR* buf, int size, int flags, const struct sockaddr FAR* to, int tolen);
參數說明:
s:套接字
buf:待發送數據的緩沖區
size:緩沖區長度
flags:調用方式標志位, 一般為 0, 改變 Flags,將會改變 Sendto 發送的形式
addr:(可選)指針,指向目的套接字的地址
tolen:addr 所指地址的長度
返回值:
如果成功,則返回發送的字節數,失敗則返回 SOCKET_ERROR。
5) 接收連接請求:
函數原型:
int accept(int fd, struct socketaddr* addr, socklen_t* len);
參數說明:
fd:套接字描述符。
addr:返回連接著的地址
len:接收返回地址的緩沖區長度
返回值:
成功返回客戶端的文件描述符,失敗返回 -1。
二、Socket的基本使用
Objective-C
包含頭文件 ??
創建 Socket
連接到服務器
發送數據
接收數據
關閉連接
三、Socket聊天
Objective-C
四、Socket網絡訪問
請求:
1、請求行
GET / HTTP/1.1
方法 GET
路徑 /
協議 HTTP 1.1
2、請求頭
Host: localhost 主機
User-Agent: 告訴服務器客戶端的類型
Accept: 告訴服務器客戶端支持的格式
Accept-Language: 告訴服務器客戶端的語言
Accept-Encoding: 告訴服務器客戶端支持的壓縮格式
響應:
1、狀態行
HTTP/1.1 200 OK
協議 HTTP 1.1
狀態碼:
200 成功
404 頁面沒找到
301 內容沒變化,用在緩存
2、響應頭(主要在開發下載應用的時候使用的)
Date: Tue, 24 Mar 2015 01:52:25 GMT 訪問日期
Server: Apache/2.4.9 (Unix) 訪問服務器的類型
Content-Location: index.html.en 訪問的文件名
Content-Length: 45 訪問文件的大小
Content-Type: text/html 訪問文件的類型
3、數據實體
訪問服務器最需的,相當于 NSURLConnection 異步方法回調中的 data。
Objective-C