先來了解下目前主流的網路協議
要想理解socket首先得熟悉一下TCP/IP協議族, TCP/IP(Transmission Control Protocol/Internet Protocol)即傳輸控制協議/網間協議,定義了主機如何連入因特網及數據如何再它們之間傳輸的標準,
從字面意思來看TCP/IP是TCP和IP協議的合稱,但實際上TCP/IP協議是指因特網整個TCP/IP協議族。不同於ISO模型的七個分層,TCP/IP協議參考模型把所有的TCP/IP系列協議歸類到四個抽象層中
應用層:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等
傳輸層:TCP,UDP
網絡層:IP,ICMP,OSPF,EIGRP,IGMP
數據鏈路層:SLIP,CSLIP,PPP,MTU
每一抽象層建立在低一層提供的服務上,並且爲高一層提供服務,看起來大概是這樣子的
我們知道兩個進程如果需要進行通訊最基本的一個前提能能夠唯一的標示一個進程,在本地進程通訊中我們可以使用PID來唯一標示一個進程,但PID
只在本地唯一,網絡中的兩個進程PID衝突機率很大,這時候我們需要另闢它徑了,我們知道IP層的ip地址可以唯一標示主機,而TCP層協議和端口號可
以唯一標示主機的一個進程,這樣我們可以利用ip地址+協議+端口號唯一標示網絡中的一個進程。
能夠唯一標示網絡中的進程後,它們就可以利用socket進行通信了,什麼是socket呢?我們經常把socket翻譯爲套接字,socket是在應用層和傳輸層之
間的一個抽象層,它把TCP/IP層複雜的操作抽象爲幾個簡單的接口供應用層調用已實現進程在網絡中通信。
socket通信流程
socket是"打開—讀/寫—關閉"模式的實現,以使用TCP協議通訊的socket爲例,其交互流程大概是這樣子的
服務器根據地址類型(ipv4,ipv6)、socket類型、協議創建socket
服務器爲socket綁定ip地址和端口號
服務器socket監聽端口號請求,隨時準備接收客戶端發來的連接,這時候服務器的socket並沒有被打開
客戶端創建socket
客戶端打開socket,根據服務器ip地址和端口號試圖連接服務器socket
服務器socket接收到客戶端socket請求,被動打開,開始接收客戶端請求,直到客戶端返回連接信息。這時候socket進入阻塞狀態,所謂阻塞即accept()方法一直到客戶端返回連接信息後才返回,開始接收下一個客戶端諒解請求
客戶端連接成功,向服務器發送連接狀態信息
服務器accept方法返回,連接成功
客戶端向socket寫入信息
服務器讀取信息
客戶端關閉
服務器端關閉
三次握手
在TCP/IP協議中,TCP協議通過三次握手建立一個可靠的連接
第一次握手:客戶端嘗試連接服務器,向服務器發送syn包(同步序列編號Synchronize Sequence Numbers),syn=j,客戶端進入SYN_SEND狀態等待服務器確認
第二次握手:服務器接收客戶端syn包並確認(ack=j+1),同時向客戶端發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態
第三次握手:第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手
定睛一看,服務器socket與客戶端socket建立連接的部分其實就是大名鼎鼎的三次握手
IOS 中 Socket 的應用
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
/**
參數
domain: 協議域,AF_INET
type: Socket 類型,SOCK_STREAM/SOCK_DGRAM
protocol: IPPROTO_TCP
返回值
socket
*/
int clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
/**
參數
1> 客戶端socket
2> 指向數據結構sockaddr的指針,其中包括目的端口和IP地址
3> 結構體數據長度
返回值
0 成功/其他 錯誤代號
*/
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(12345);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
int connectResult = connect(clientSocket, (const struct sockaddr *)&serverAddr, sizeof(serverAddr));
/**
參數
1> 客戶端socket
2> 發送內容地址
3> 發送內容長度
4> 發送方式標誌,一般爲0
返回值
如果成功,則返回發送的字節數,失敗則返回SOCKET_ERROR
*/
const char *sendMessage = "hello";
ssize_t sendLen = send(clientSocket, sendMessage, strlen(sendMessage), 0);
/**
參數
1> 客戶端socket
2> 接收內容緩衝區地址
3> 接收內容緩存區長度
4> 接收方式,0表示阻塞,必須等待服務器返回數據
返回值
如果成功,則返回讀入的字節數,失敗則返回SOCKET_ERROR
*/
uint8_t buffer[1024];
ssize_t recvLen = recv(clientSocket, &buffer, sizeof(buffer), 0);
NSData *data = [NSData dataWithBytes:buffer length:recvLen];
NSString *recvMessage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
-
- Socket就是爲網絡服務提供的一種機制
- 在Unix中,網絡既是Socket,並不侷限在TCP/UDP
- Socket可以用於自定義協議
- 通信的兩端都是Socket
- 網絡通信其實就是Socket間的通信
- 數據在兩個Socket間通過IO傳輸
- Socket開始是純C語言的,是跨平臺的