本文介紹UDP協議的簡單模擬場景demo.
首先介紹一下每個字眼:
HTTP/XMPP: 都是數據傳輸格式的協議.(這里不作累述)
TCP和UDP: 都是數據傳輸方式的協議.比如說我要給你錢, 我是以手把手的方式拿給你呢還是以快遞的方式寄給你呢.
TCP(傳輸控制協議)
- 需要經過三次握手建立連接,形成一條傳輸通道,不斷傳輸數據
- 傳輸數據的大小不受限制
- 是安全可靠的協議,但是速度稍慢
UDP(用戶數據報協議)
- 不需要建立連接, 把數據封裝成數據包扔給對面
- 每個數據包大小限制在64K內
- 因為不建立連接,所以對方可能收到也可能收不到數據(丟包),因此是不安全的協議, 但是速度比較快
什么時候用TCP,什么時候用UDP:##
對速度要求比較高的時候使用UDP, 對數據安全要求比較高的時候使用TCP.
比如說視頻聊天, QQ聊天, 就用UDP; 數據傳輸,文件下載,就用TCP.
假如對于視頻聊天來說,如果畫質優先那就選用TCP, 如果流暢度優先那就選用UDP.
什么是Socket###
Socket應用于兩個不同客戶端之間的通信及數據傳輸.中文名字叫套接字.
編程源于生活. 打個活生生的例子來說, 汽車和加油機.我們如果想把加油機里面的油輸到汽車上, 那么汽車這邊需要有一個端口, 加油機這邊也要有一個端口, 兩邊端口各加一個套接頭套著(好比adaptor),然后中間連上管道來輸油. 我認為Socket的角色就是這個套接頭.
簡單來說, 要想在兩個客戶端之間傳數據, 那么兩個客戶端各自都要有一個Socket.
UDP協議下,一個客戶端如何發數據給另一個客戶端
如果客戶端B想給客戶端A發數據, 那么就需要知道兩個東西, 一個是客戶端A的IP地址, 一個是端口號.就好像你讓我給一部車加油, 我需要知道是哪部車(IP)和這部車的哪個洞是加油洞(端口號).
下面我們用demo模擬兩個客戶端間通過UDP協議來發送數據.
思路如下:
客戶端A:
1.用Xcode新建一個OC工程clientA作為客戶端A, 它是接收方.
2.導入socket框架(把下載好的GCDAsyncUdpSocket.h和.m拖進工程即可)并import頭文件
3.創建Socket對象
4.連接端口號
5.開啟接收數據
6.遵守GCDAsyncUdpSocketDelegate協議,實現didReceiveData的代理方法,在里面拿到接收的數據.
客戶端B:
1.用Xcode新建一個命令行工程clientB作為客戶端B,它是發送方.
2.導入socket框架并import頭文件(同上)
3.創建Socket對象
4.調用方法發送數據給客戶端A(需要知道clientA的IP和端口號)
代碼如下:
客戶端A(clientA):
#import "ViewController.h"
#import "GCDAsyncUdpSocket.h"
@interface ViewController ()<GCDAsyncUdpSocketDelegate>
@property(nonatomic, strong) GCDAsyncUdpSocket *udpSocket;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//創建套接字socket
self.udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
//綁定端口號
NSError *error = nil;
[self.udpSocket bindToPort:5555 error:&error];
if (!error) {
NSLog(@"綁定端口成功");
}else {
NSLog(@"綁定端口失敗");
}
//開啟監聽數據接收
[self.udpSocket beginReceiving:&error];
if (!error) {
NSLog(@"開啟監聽數據成功");
}else {
NSLog(@"開啟監聽數據失敗");
}
}
//實現代理方法接收數據
-(void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext{
//把接收到的data轉化為NSString
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//打印string
NSLog(@"接收到數據 %@", string);
}
@end
客戶端B(clientB):
#import <Foundation/Foundation.h>
#import "GCDAsyncUdpSocket.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//創建udpSocket對象
GCDAsyncUdpSocket *udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:nil delegateQueue:dispatch_get_main_queue()];
//創建要發送的data
NSString *string = @"Wales萬歲,Wales永垂不朽!";
NSData *sentData = [string dataUsingEncoding:NSUTF8StringEncoding];
//發送data到clientA
//Host: 要發送到的IP地址
//port:要發送到的端口號
[udpSocket sendData:sentData toHost:@"127.0.0.1" port:5555 withTimeout:-1 tag:0];
//為了防止該程序一啟動就掛掉
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
兩個工程(客戶端)一起運行后, 客戶端B給A發送了一個數據,在客戶端A中打印的結果如下: