iOS學習筆記4-GCDAsyncUdpSocket的使用(實現非同步傳送接收資料)
做專案的時候用到了GCDAsyncUdpSocket,所以在此總結下它的用法,作為筆記;
GCDAsyncUdpSocket簡介
GCDAsyncUdpSocket開源類庫是以蘋果的GCD多工處理機制完成的一個非同步互動套接字通訊。如果需要使用同步的,則去尋找AsyncUdpSocket就可以了。該開源庫完成了UDP之間的通訊,使得UDP通訊的程式設計變得更加簡單;
使用方法:
1.原始碼下載以及匯入:
原始碼在谷歌上一搜便有,下面給出github的地址:https://github.com/robbiehanson/CocoaAsyncSocket
下載即可。
該開源庫裡面也有相應地示例程式碼,但如果需要用到我們的程式碼裡面,只需要複製出GCDAsyncUdpSocket.h,GCDAsyncUdpSocket.m
2.定義一個GCDAsyncUdpSocket物件
首先,需要匯入標頭檔案,在需要引用GCDAsyncUdpSocket的地方(如我定義一個網路類UdpAssociation.m)的.h檔案中匯入GCDAsyncUdpSocket.h檔案
如:
#import "GCDAsyncUdpSocket.h"
接著,在UdpAssociation的標頭檔案裡改成:
@interface UdpAssociation : NSObject <GCDAsyncUdpSocketDelegate>
代表著類UdpAssociation要遵守這個協議;
接著,在類UdpAssociation中定義一個GCDAsyncUdpSocket物件
如:
GCDAsyncUdpSocket *udpSocket;
3.初始化
在初始化函式中需要完成幾個步驟:
·例項化一個GCDAsyncUdpSocket物件
如:
udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
解釋:
檢視它的原始碼,會發現還有好幾種初始化的方法,這裡選用的是其中的一種,initWithDelegate:self設定代理是自己,意味著自己會接受到與該協議相關的任何訊息,delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);這裡給delegateQueue加的是全域性併發的佇列,也可以給其它的佇列;
·接著繫結通訊埠
NSError *error = nil;
if(![udpSocket bindToPort :servicePort error:&error])
{
NSLog(@"error in bindToPort");
//return;
}
·到此所有初始化工作已經完成。
4.寫代理函式
該開源庫總共需要寫6個代理函式:
可以檢視協議標頭檔案可得:
@protocol GCDAsyncUdpSocketDelegate
@optional
/**
* By design, UDP is a connectionless protocol, and connecting is not needed.
* However, you may optionally choose to connect to a particular host for reasons
* outlined in the documentation for the various connect methods listed above.
*
* This method is called if one of the connect methods are invoked, and the connection is successful.
**/
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didConnectToAddress:(NSData *)address;
/**
* By design, UDP is a connectionless protocol, and connecting is not needed.
* However, you may optionally choose to connect to a particular host for reasons
* outlined in the documentation for the various connect methods listed above.
*
* This method is called if one of the connect methods are invoked, and the connection fails.
* This may happen, for example, if a domain name is given for the host and the domain name is unable to be resolved.
**/
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotConnect:(NSError *)error;
/**
* Called when the datagram with the given tag has been sent.
**/
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag;
/**
* Called if an error occurs while trying to send a datagram.
* This could be due to a timeout, or something more serious such as the data being too large to fit in a sigle packet.
**/
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error;
/**
* Called when the socket has received the requested datagram.
**/
(void)udpSocket:(GCDAsyncUdpSocket *)sock
didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext;
/**
* Called when the socket is closed.
**/
- (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError *)error;
@end
其中最重要的是寫好接收的回撥函式就可以了:
(void)udpSocket:(GCDAsyncUdpSocket *)sock
didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext;
data就是接收到得資料,在該函式寫好具體的處理函式就好了。
5.開始傳送或者接受:
·首先談談接收:
在初始化的最後加上下面接收這句,便開始接收了(一旦有資料傳送過來)。
首先接收是非同步的,所以對於大量資料同時傳送的時候要注意接收的順序問題;
接著,該開源庫接收也有兩種方法:
[udpSocket receiveOnce:&error];
[udpSocket beginReceiving:&error];
兩種的區別是:[udpSocket receiveOnce:&error]只能接收一次資料,而在正常的UDP通訊中是可不停地接收的,如果需要不停地接收那就適合使用第二條[udpSocket beginReceiving:&error];
但兩者又有關聯,兩者是可以互相轉化的,比如,在某種情況下,你需要只接受一次資料,那就可以先選用[udpSocket receiveOnce:&error];接下來在完成某件事情後,你需要開始正常的不停的接收了,這時候只需要再寫一句:[udpSocket beginReceiving:&error];這樣就能夠轉化了。
·傳送
傳送比較簡答,只需要在需要傳送資料的地方加上:
[udpSocket sendData:sendData toHost:serviceAddress port:servicePort withTimeout:-1 tag:tag];
看原始碼也會發現還有許多中傳送的方法,具體可以去原始碼檢視;
注意:這裡的傳送也是非同步的。
withTimeout設定成-1代表超時時間為-1,即永不超時;
同時這裡的tag也可以作為一個標籤使用,具體用法可以參考以下博文:
《GCDAsyncSocket類庫,IOS下TCP通訊使用心得》
好了,到此,你應該能夠利用該開源庫進行基本的通訊了!