網(wǎng)絡(luò)通訊三要素
1.IP地址(主機(jī)名)
網(wǎng)絡(luò)中設(shè)備的標(biāo)示
不易記憶芋簿,可以用主機(jī)名
本地回環(huán)地址:127.0.0.1主機(jī)名:localhost
每臺計(jì)算機(jī)都有一個(gè)127.0.0.1
如果 127.0.0.1ping不通,說明網(wǎng)卡不工作
如果本機(jī)地址ping不通,說明網(wǎng)線壞了
2.端口號
用于標(biāo)示進(jìn)程的邏輯地址,不同進(jìn)程的標(biāo)示
有效端口:0~65535
其中0~1024由系統(tǒng)使用或者保留端口
開發(fā)中不要使用1024以下的端口
3.傳輸協(xié)議
TCP(傳輸控制協(xié)議)
UDP(數(shù)據(jù)報(bào)文協(xié)議)
通過IP找機(jī)器针贬,通過端口找程序赴背,通過協(xié)議確定如何傳輸數(shù)據(jù)
常見網(wǎng)絡(luò)協(xié)議
協(xié)議 ? ?端口 ? ? ?說明
HTTP ? ? ?80 ? ? ? ? ?超文本傳輸協(xié)議
HTTPS ? ?443 ? ? ? ? ?HTTP+SSL,HTTP的安全版
FTP ? ? ? ?20/21/990 ? ?文件傳輸協(xié)議
POP ? ? ? 110 ? ? ? 郵局協(xié)議
SMTP ? ? ?25 ? ? ?簡單郵件傳輸協(xié)議
telnet ? ? 23 ? ? ?遠(yuǎn)程終端協(xié)議
SSH ? ? ?22 ? ? ?Secure Shell
TCP & UDP
UDP(用戶數(shù)據(jù)報(bào)協(xié)議)
只管發(fā)送嫉称,不確認(rèn)對方是否接收到
將數(shù)據(jù)源和目的封裝成數(shù)據(jù)包中,不需要建立連接
每個(gè)數(shù)據(jù)報(bào)的大小限制在64K之內(nèi)
因?yàn)闊o需連接灵疮,因此是不可靠協(xié)議
不需要建立連接织阅,速度快
應(yīng)用場景:多媒體教室/網(wǎng)絡(luò)流媒體
TCP(傳輸控制協(xié)議)
建立連接,形成傳輸數(shù)據(jù)的通道
在連接中進(jìn)行大數(shù)據(jù)傳輸(數(shù)據(jù)大小不受限制)
通過三次握手完成連接始藕,是可靠協(xié)議蒲稳,安全送達(dá)
必須建立連接,效率會稍低
Socket(套接字層伍派、插座)
Socket就是為網(wǎng)絡(luò)服務(wù)提供的一種機(jī)制
通信的兩端都是Socket
網(wǎng)絡(luò)通信其實(shí)就是Socket間的通信
數(shù)據(jù)在兩個(gè)Socket間通過I/O傳輸
Socket是純C語言的江耀,是跨平臺的
長/短連接 & 心跳包
短連接
數(shù)據(jù)請求結(jié)束后,立即斷開連接
能夠及時(shí)釋放服務(wù)器資源
讓服務(wù)器能夠?yàn)楦嗟挠脩籼峁┓?wù)
長連接
一旦連接建立之后诉植,始終保持連接狀態(tài)
后續(xù)只需發(fā)送和接收數(shù)據(jù)即可祥国,數(shù)據(jù)響應(yīng)更及時(shí)
長連接對服務(wù)器資源占用比較大
對交互響應(yīng)要求快的應(yīng)用,例如即時(shí)通訊,需要使用長連接
心跳包
是檢測長連接的重要技術(shù)手段
可以由服務(wù)器發(fā)送,定時(shí)向客戶端發(fā)送小數(shù)據(jù)舌稀,根據(jù)回執(zhí)判斷客戶端是否在線
也可以由客戶端發(fā)送,定時(shí)向服務(wù)器發(fā)送小數(shù)據(jù)啊犬,報(bào)告客戶端當(dāng)前在線
Socket 加載百度
修改接收函數(shù)
- (NSString*)sendAndRecv:(NSString*)msg {
// 1. 發(fā)送
ssize_t sendLen = send(self.clientSocket, msg.UTF8String, strlen(msg.UTF8String),0);
NSLog(@"發(fā)送 %ld %tu %ld", sendLen, msg.length, strlen(msg.UTF8String));
// 2. 接收
uint8_t buffer[1024];
NSMutableData *dataM = [NSMutableData data];
ssize_t recvLen = -1;while(recvLen !=0) {
recvLen = recv(self.clientSocket, buffer,sizeof(buffer),0);
[dataM appendBytes:buffer length:recvLen];
}
NSString*result = [[NSStringalloc] initWithData:dataM encoding:NSUTF8StringEncoding];
// 3. 斷開連接
[selfdisconnect];
returnresult;
}
發(fā)送請求
- (void)viewDidLoad {
[superviewDidLoad];
if(![selfconnectToHost:@"61.135.185.17"port:80])
{NSLog(@"連接失敗");return;
}
// 發(fā)送請求
NSString*request =@"GET / HTTP/1.1\r\n""Host: m.baidu.com\r\n""User-Agent: iPhone AppleWebKit\r\n""Connection: Close\r\n\r\n";
NSString*resposne = [selfsendAndRecv:request];
// 獲取
htmlNSRangerange = [resposne rangeOfString:@"\r\n\r\n"];
if(range.location!=NSNotFound) {
NSString*html = [resposne substringFromIndex:range.location+ range.length];? ? ? ? [self.webViewloadHTMLString:html baseURL:[NSURLURLWithString:@"http://m.baidu.com"]];
}else{
NSLog(@"加載失敗");
}
}
Socket 聊天
搭建界面
自動(dòng)布局 & 代碼連線
///? 主機(jī)地址
@property(weak,nonatomic)IBOutletUITextField *hostName;
///? 端口號
@property(weak,nonatomic)IBOutletUITextField *portNumber;
///? 發(fā)送消息文字
@property(weak,nonatomic)IBOutletUITextField *messageText;
///? 接收文字標(biāo)簽
@property(weak,nonatomic)IBOutletUILabel*recvLabel;
///? 發(fā)送按鈕
@property(weak,nonatomic)IBOutletUIButton*sendButton;
調(diào)整連接到主機(jī)代碼,添加參數(shù)
/// 連接
- (BOOL)connectToHost:(NSString*)hostName port:(int)port {
// 1. socket
self.clientSocket= socket(AF_INET, SOCK_STREAM,0);
NSLog(@"%d",self.clientSocket);
// 2. 連接
structsockaddr_in serverAddr;
serverAddr.sin_family= AF_INET;
serverAddr.sin_addr.s_addr= inet_addr(hostName.UTF8String);? ? serverAddr.sin_port= htons(port);
return connect(self.clientSocket, (conststructsockaddr *)&serverAddr,sizeof(serverAddr)) ==0;
}
實(shí)現(xiàn)連接功能
- (IBAction)connect {BOOLresult = [selfconnectToHost:self.hostName.textport:self.portNumber.text.intValue];
self.sendButton.enabled= result;self.recvLabel.text= result ?@"成功":@"失敗";
}
調(diào)整發(fā)送和接收方法壁查,添加參數(shù)
///? 發(fā)送和接收
- (NSString*)sendAndRecv:(NSString*)msg {
// 1. 發(fā)送
ssize_t sendLen = send(self.clientSocket, msg.UTF8String, strlen(msg.UTF8String),0);
NSLog(@"發(fā)送 %ld %tu %ld", sendLen, msg.length, strlen(msg.UTF8String));
// 2. 接收
uint8_t buffer[1024];
ssize_t recvLen = recv(self.clientSocket, buffer,sizeof(buffer),0);
NSLog(@"接收了 %ld %ld", recvLen,sizeof(buffer));
NSString*result = [[NSStringalloc] initWithBytes:buffer length:recvLen encoding:NSUTF8StringEncoding];
returnresult;
}
發(fā)送和接收操作
- (IBAction)send {
self.recvLabel.text= [selfsendAndRecv:self.messageText.text];
}