socket 入門回顧, 直接上步驟
一、基礎知識
1.三大基礎認識(IP
端口
協議
)
IP 端口 協議.png
- IP地址,(2^8)^4 ,可表示42億網絡設備,可貌似連世界總人口的明顯不夠吧。so,??
- 外網/內網, 路由器,解決這些問題。你要是訪問百度,全國各地,可能分配了不同的IP。
- 服務器有不同的服務 ,前端 通過端口 來訪問響應服務 ,但一般不是直接通過端口號訪問服務 , 通過協議
服務器端口.png
2.終端ping的玩一下
- ①ping 127.0.0.1 不通 和 ②ping 192.168.31.180不通, 兩者是有區別的。
- 前者不通代表網卡問題, 后者則是通過ping 路由器下發到子節點本機的,可能路由的問題了。
image.png
3.協議 (7層模型)
7層模型.png
- 計算機起源
第一臺computer用來打炮的
后來,計算機越來越多, 存儲數據方式-->磁帶打孔 存儲二進制
再后來, 軟盤(媒介) 發明作為計算機之間通信數據方式
后來,科學家發現 二進制數據 與 電流電信號(高低電平)一樣嘛,ok,走入正軌。
- 七層模型底下3層(硬件) ,由通信芯片搞定,芯片代碼已經寫死(效率非常高), 咱們是觸碰不到的, 咱就是站在巨人肩膀上開發
- socket是在傳輸層, 倆協議TCP、UDP。TCP/IP 協議是分不開的 , IP協議其實是在網絡層,我們用不到的拿不到的
image.png
- 上面三層,比較模糊,表示層、會話層 許多協議都廢棄掉了,合成為一層 -- 應用層
從傳輸層 拿到data, 怎么知道是一部電影還是一個小秘密呢,這就需要建立一個網絡會話(會話層),通過http協議在網絡會話中,按照協議特定的格式 對二進制進行解析
- 傳輸層, TCP/UDP保證計算機之間通信中拿到準確的data ,但我咋知道你是啥數據呢??
- 會話層,兩個互相通 信的應用進程之間,建立、組織和協調其交互(Interaction)
- 表示層, 負責在不同的數據格式之間進行轉換操作(編碼、加密、壓縮)
4.深入協議UDP
& TCP
image.png
小問題: 猜一猜咱開發中幾種場景,用的UDP 還是TCP ?? (a)游戲 (b)大文件下載
答案: (a)UDP 會掉幀(掉1個64k內的數據包) (b)TCP (安全 完整, 效率低) because??
注意點: TCP連接握手三次,斷開握手四次
5.socket理解
image.png
想到socket 立馬想到 IP port ~
兩手機qq聊天, 手機a通過IP找到手機,通過port找到應用程序,然后建立連接,ok交流吧"約嗎?"
6.socket通訊示意圖
image.png
socket是跨平臺的,無論什么平臺(Android, ios ,c++...) 底層通訊都是??圖(此圖乃真理也,經久不衰)
二、擼代碼
- 核心代碼
socket即網絡, 這就是咱所用網絡(?NSURLSession/Connection/AFN...
等)最底層代碼了
// 創建
int socket(int domain, int type, int protocol);
// 連接
int connect(int, const struct sockaddr *, socklen_t) __DARWIN_ALIAS_C(connect);
// 發送數據
ssize_t send(int, const void *, size_t, int) __DARWIN_ALIAS_C(send); // void * 萬能指針
// 讀取數據
ssize_t recv(int, void *, size_t, int) __DARWIN_ALIAS_C(recv);
// 關閉連接
int close(int);
-
socket連接成功
- image.png
-
步驟簡單:
1.敲下??圖中代碼(設置本機
和12345
端口號)
2.終端命令行使 始終監聽本地計算機12345端口的數據 ??$ nc -lk 12345
Netcat , 終端下 用于調試檢查網絡的工具包,可用于創建TCP/IP連接
3.run
懶人copy的如下??
// 頭文件引入
import <sys/socket.h> // socket
#import <netinet/in.h> // 互聯網
#import <arpa/inet.h> // 互聯網參數
// 1. 創建socket
/**
domain: 協議域 AF_INET -> IPV4
type: socket類型 ,SOCK_STREAM -> TCP , SOCK_DGRAM -> UDP
protocol: IPPROTO_TCP, 如果0 , 自動選擇,根據上個(第二個)參數而定
return: socket
*/
int clientSocket = socket(AF_INET, SOCK_STREAM, 0); // 6
// 2. 連接
/**
client socket:
(地址)指針: 指向 結構體sockaddr (目標(server)的 port ip)
結構體數據長度:
return: 0 成功
*/
struct sockaddr_in serverAddr;
serverAddr.sin_port = htons(12345); // htons 該宏 專用于寫 端口號 // 20480(高地位互換)
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 底層ip地址也是一串二進制
int connResult = connect(clientSocket, (const struct sockaddr *)&serverAddr, sizeof(serverAddr));
if (connResult == 0) {
NSLog(@"socket connet successfully");
}else{
NSLog(@"socket connet fail %zd",connResult);
return;
}
// 3. 發送數據
/**
參數
client socket:
發送內容指針
發送內容長度
發送方式標志, 一般為0
返回值
如果成功, 則返回字節數
*/
NSString * msg = @"hello socket";
//const char * msg1 = "hello socket 1";
ssize_t sendLen = send(clientSocket, msg.UTF8String, strlen(msg.UTF8String), 0);
NSLog(@"send %ld",sendLen);
// 4. 讀取數據
.
.
. // 更多請去GitHub Demo
}
-
UI搭建
image.png
三、拓展
- 思考 :
如何通過socket連接百度server呢? 直接將127.0.0.1換成www.baidu.com可以嗎? - 接下來, try一try~ ??圖
image.png
but: 發現 發送hello, 沒有響應, why ? (server根本看不懂 我發的"hello")
因為: 它是網頁請求, 需要使用http協議, socket是最底層的了,可沒有幫你封裝處理http .
-
看看網頁請求格式
真正發送給服務器的數據.png看到??request header, 這就是真正發送給服務器的數據
再 try ~
將那些request header內容 復制到 發送內容中, 通過socket發送,即可收到server的response了
超懶人 點擊 github | <a >demo</a> 下載 調試 。
祝愿有所收獲哦 ~ _ ~