1. 程式人生 > >iOS學習筆記4-GCDAsyncUdpSocket的使用(實現非同步傳送接收資料)

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通訊使用心得》

好了,到此,你應該能夠利用該開源庫進行基本的通訊了!