iOS之Socket的使用-AsyncSocket
iOS有原生的socket,但AsyncSocket這個第三方庫,對socket的封裝比較好,本文就是基于AsyncSocket的使用介紹。
環境
下載AsyncSocket https://github.com/roustem/AsyncSocket類庫,將RunLoop文件夾下的AsyncSocket.h,AsyncSocket.m,AsyncUdpSocket.h,AsyncUdpSocket.m 文件拷貝到自己的project中。
添加CFNetwork.framework, 再使用socket的文件頭:
使用
一、socket 連接
即時通訊最大的特點就是實時性,基本感覺不到延時或是掉線,所以必須對socket的連接進行監視與檢測,在斷線時進行重新連接,如果用戶退出登錄,要將socket手動關閉,否則對服務器會造成一定的負荷。
一般來說,一個用戶只能有一個正在連接的socket,所以這個socket變量必須是全局的,可以使用單例或是AppDelegate進行數據共享,本文使用單例。如果對一個已經連接的socket對象再次進行連接操作,會拋出異常(不可對已經連接的 socket進行連接)程序崩潰,所以在連接socket之前要對socket對象的連接狀態進行判斷。
使用socket進行即時通訊還有一個必須的操作,即對服務器發送心跳包,每隔一段時間對服務器發送長連接指令(指令不唯一,由服務器端指定,包括使用socket發送消息,發送的數據和格式都是由服務器指定),如果沒有收到服務器的返回消息,AsyncSocket會得到失去連接的消息,我們可以 在失去連接的回調方法里進行重新連接。
- 先創建一個單例,命名為Singleton
- 連接(長連接)
在.h文件中聲明socket變量和方法,并聲明代理; 在.m中實現,連接時host與port都是由服務器指定。
//.h@property (nonatomic, strong) AsyncSocket *socket; // socket @property (nonatomic, copy ) NSString *socketHost; // socket的Host @property (nonatomic, assign) UInt16 socketPort; // socket的prot- (void)socketConnectHost; //socket連接//.m- (void)socketConnectHost {self.socket = [[AsyncSocket alloc]initWithDelegate:self];NSError *error = nil;[self.socket connectToHost:self.socketHost onPort:self.socketPort withTimeout:3 error:&error]; }- 心跳
心跳通過計時器來實現:在singleton.h中聲明一個定時器;在singleton.m中實現連接成功回調方法,并在此方法中初始化定時器,發送心跳在后文向服務器發送數據時說明。
//singleton.h@property (nonatomic, retain) NSTimer *connectTimer; // 計時器//singleton.m#pragma mark - 連接成功回調 - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {NSLog(@"socket連接成功");// 每隔30s像服務器發送心跳包self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(longConnectToSocket) userInfo:nil repeats:YES];// 在longConnectToSocket方法中進行長連接需要向服務器發送的訊息[self.connectTimer fire]; }二、socket斷開連接與重連
- 斷開連接
失去連接有幾種情況,服務器斷開,用戶主動cut,還可能有如QQ其他設備登錄被掉線的情況,不管那種情況,都能收到socket回調方法返回訊息,如果是用戶退出登錄或是程序退出而需要手動cut,在cut前對socket的userData賦予一個值來標記為用戶退出,這樣可以在收到斷開信息時判斷究竟是什么原因導致的掉線。
在.h文件中聲明一個枚舉類型和斷開連接方法,并在.m中實現
//.henum{SocketOfflineByServer,// 服務器掉線,默認為0SocketOfflineByUser, // 用戶主動cut };- (void)cutOffSocket; // 斷開socket連接//.m// 切斷socket- (void)cutOffSocket {self.socket.userData = SocketOfflineByUser;// 聲明是由用戶主動切斷[self.connectTimer invalidate];[self.socket disconnect]; }- 重連
三、socket發送與接收數據
- 發送數據
實現心跳連接未完成的方法
// 心跳連接 - (void)longConnectToSocket {// 根據服務器要求發送固定格式的數據,假設為指令@"longConnect",但是一般不會是這么簡單的指令NSString *longConnect = @"longConnect";NSData *dataStream = [longConnect dataUsingEncoding:NSUTF8StringEncoding];[self.socket writeData:dataStream withTimeout:1 tag:1]; }socket發送數據是以棧的形式存放,所有數據放在一個棧中,存取時會出現粘包的現象,所以很多時候服務器在收發數據時是以先發送內容字節長度, 再發送內容的形式,得到數據時也是先得到一個長度,再根據這個長度在棧中讀取這個長度的字節流,如果是這種情況,發送數據時只需在發送內容前發送一個長 度,發送方法與發送內容一樣,假設長度為8
NSData *dataStream = [@8 dataUsingEncoding:NSUTF8StringEncoding]; [self.socket writeData:dataStream withTimeout:1 tag:1];- 接收數據
四、簡單使用說明
在用戶登錄后的第一個界面進行socket的初始化連接操作,在得到數據后,將所需要顯示的數據放在singleton中,對變量進行監聽后做出相應的操作即可。
[Singleton sharedInstance].socketHost = @"192.186.100.21";// host設定[Singleton sharedInstance].socketPort = 10045;// port設定// 在連接前先進行手動斷開[Singleton sharedInstance].socket.userData = SocketOfflineByUser;[[Singleton sharedInstance] cutOffSocket];// 確保斷開后再連,如果對一個正處于連接狀態的socket進行連接,會出現崩潰[Singleton sharedInstance].socket.userData = SocketOfflineByServer;[[Singleton sharedInstance] socketConnectHost];總結
以上是生活随笔為你收集整理的iOS之Socket的使用-AsyncSocket的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS开发之ReplayKit框架学习
- 下一篇: iOS开发之实现毛玻璃效果及图片模糊效果