什么是Socket
網(wǎng)絡(luò)上的兩個(gè)程序通過(guò)一個(gè)雙向的通信連接實(shí)現(xiàn)數(shù)據(jù)的交換,這個(gè)連接的一端稱為一個(gè)socket。
實(shí)際上socket是對(duì)TCP/IP協(xié)議的封裝,Socket本身并不是協(xié)議,而是一個(gè)調(diào)用接口(API)。
俗稱套接字
他介與應(yīng)用層和傳輸層之間
IP協(xié)議對(duì)應(yīng)于網(wǎng)絡(luò)層,TCP協(xié)議對(duì)應(yīng)于傳輸層,而HTTP協(xié)議對(duì)應(yīng)于應(yīng)用層。
TPC/IP協(xié)議是傳輸層協(xié)議,主要解決數(shù)據(jù)如何在網(wǎng)絡(luò)中傳輸,而HTTP是應(yīng)用層協(xié)議,主要解決如何包裝數(shù)據(jù)。
Socket自定義傳輸
建立Socket連接至少需要一對(duì)套接字,其中一個(gè)運(yùn)行于客戶端,稱為ClientSocket ,另一個(gè)運(yùn)行于服務(wù)器端,稱為ServerSocket 。
套接字之間的連接過(guò)程分為三個(gè)步驟:服務(wù)器監(jiān)聽(tīng),客戶端請(qǐng)求,連接確認(rèn)。
下面是流程圖

一.開(kāi)啟服務(wù)器ServerSocket
對(duì)于我們的Mac來(lái)說(shuō)開(kāi)啟nc netcat 打卡命令行輸入nc -lk? 端口號(hào)

socket() -->bind() -- >listen()-- accpet() -- 客戶端和服務(wù)器開(kāi)始讀寫(xiě)操作 -- 收到客戶端關(guān)閉連接請(qǐng)求消息--->關(guān)閉連接
bind()函數(shù)通過(guò)給一個(gè)未命名套接口分配一個(gè)本地名字來(lái)為套接口建立本地捆綁(主機(jī)地址/端口號(hào))
struct sockaddr_in 通過(guò)這個(gè)結(jié)構(gòu)里面內(nèi)容捆綁接口下面會(huì)描述這個(gè)接口
listen() 創(chuàng)建一個(gè)套接口并監(jiān)聽(tīng)申請(qǐng)的連接
我這篇文章主要實(shí)現(xiàn)客戶端的請(qǐng)求實(shí)現(xiàn)
二.客戶端連接請(qǐng)求
第一步創(chuàng)建socket
創(chuàng)建socket (導(dǎo)入對(duì)應(yīng)的頭文件<netinet/in.h>,<sys/socket.h>,<arpa/inet.h>)
socket(int, int, int)
第一個(gè)參數(shù) 協(xié)議域 AF_INET(ipv4)、AF_INET6(ipv6)....
第二次參數(shù):指定Socket類型。常見(jiàn)的2種
sock_stream是基于TCP的 是有保障的(即能保證數(shù)據(jù)正確傳送到對(duì)方)面向連接的SOCKET,多用于資料(如文件)傳送。
sock_dgram 是基于UDP的, 是無(wú)保障的面向消息的socket , 主要用于在網(wǎng)絡(luò)上發(fā)廣播信息。
第三個(gè)次參數(shù):指定協(xié)議? IPPROTO_TCP IPPROTO_UDP

第二步創(chuàng)建連接
connect(int, const struct sockaddr , socklen_t)? (經(jīng)過(guò)3次握手)
? ? ? ? 參數(shù)一:套接字描述符
? ? ? ? 參數(shù)二: struct sockaddr_in
? ? ? ? 參數(shù)三:參數(shù)二sockaddr的長(zhǎng)度,可以通過(guò)sizeof(struct sockaddr)獲得
? ? ? sockaddr 結(jié)構(gòu)體

第三步發(fā)送消息
s:一個(gè)用于標(biāo)識(shí)已連接套接口的描述字。
buf:包含待發(fā)送數(shù)據(jù)的緩沖區(qū)。
len:緩沖區(qū)中數(shù)據(jù)的長(zhǎng)度。
flags:調(diào)用執(zhí)行方式。一般填0
send(<#int#>, <#const void *#>, <#size_t#>, <#int#>)

第四部接收消息
recv(int, void *, size_t, int)

我模擬了一個(gè)聊天的效果
啟動(dòng)了一個(gè)定時(shí)器每過(guò)一段時(shí)間去取一次數(shù)據(jù).模擬聊天

值得注意的是recv 使用了堵塞的方式獲取數(shù)據(jù),所以把他放在子線程去做數(shù)據(jù)的接收
第五步關(guān)閉連接
close(int)

我將socket的創(chuàng)建,連接,發(fā)送,接收,和關(guān)閉封裝到一個(gè)類里面進(jìn)行操作
建立連接和接收服務(wù)器數(shù)據(jù)
本地回環(huán)地址建立服務(wù)器的連接,連接6969端口

發(fā)送數(shù)據(jù)

請(qǐng)求到數(shù)據(jù)的結(jié)果

模擬發(fā)送http的請(qǐng)求
通過(guò)命令行 獲取網(wǎng)址的地址

一般的端口號(hào)都是80

接收數(shù)據(jù)

接收數(shù)據(jù)的具體實(shí)現(xiàn)

使用socket 發(fā)送http網(wǎng)絡(luò)請(qǐng)求 App Transport Security Settings 可以繞過(guò)安全協(xié)議的限制,說(shuō)明我們高級(jí)NSURLSession 對(duì)是否遵守這個(gè)權(quán)限做了判斷
OSI七層模型
應(yīng)用層
? ? 網(wǎng)絡(luò)服務(wù)與最終用戶的一個(gè)接口。
? ? 協(xié)議有:HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP
表示層
數(shù)據(jù)的表示、安全、壓縮。(在五層模型里面已經(jīng)合并到了應(yīng)用層)
格式有,JPEG、ASCll、DECOIC、加密格式等
會(huì)話層
建立、管理、終止會(huì)話。(在五層模型里面已經(jīng)合并到了應(yīng)用層)
對(duì)應(yīng)主機(jī)進(jìn)程,指本地主機(jī)與遠(yuǎn)程主機(jī)正在進(jìn)行的會(huì)話
傳輸層
定義傳輸數(shù)據(jù)的協(xié)議端口號(hào),以及流控和差錯(cuò)校驗(yàn)。
協(xié)議有:TCP UDP,數(shù)據(jù)包一旦離開(kāi)網(wǎng)卡即進(jìn)入網(wǎng)絡(luò)傳輸層
網(wǎng)絡(luò)層
進(jìn)行邏輯地址尋址,實(shí)現(xiàn)不同網(wǎng)絡(luò)之間的路徑選擇。
協(xié)議有:(最主要的主要)IP(IPV4 IPV6) ICMP IGMP? ARP RARP
數(shù)據(jù)鏈路層
建立邏輯連接、進(jìn)行硬件地址尋址、差錯(cuò)校驗(yàn) 等功能。
將比特組合成字節(jié)進(jìn)而組合成幀,用MAC地址訪問(wèn)介質(zhì),錯(cuò)誤發(fā)現(xiàn)但不能糾正。
物理層
建立、維護(hù)、斷開(kāi)物理連接。(由底層網(wǎng)絡(luò)定義協(xié)議)
后言:
我們開(kāi)發(fā)過(guò)程中一般都是用更加高級(jí)的api,寫(xiě)一點(diǎn)底層的是幫助我們理解客戶端和服務(wù)器的通訊過(guò)程,過(guò)年了梳理下知識(shí)點(diǎn)