你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS運用中應用AsyncSocket庫處置Socket通訊的用法講授

iOS運用中應用AsyncSocket庫處置Socket通訊的用法講授

編輯:IOS開發綜合

用socket可以完成像QQ那樣發送即時新聞的功效。客戶端和辦事端須要樹立長銜接,在長銜接的情形下,發送新聞。客戶端可以發送心跳包來檢測長銜接。

在IOS開辟中應用socket,普通都是用第三方庫AsyncSocket,不能不認可這個庫確切很壯大。下載地址CocoaAsyncSocket

特征

AsyncSocket類是支撐TCP的。
AsyncUdpSocket是支撐UDP的。
AsyncSocket是封裝了CFSocket和CFSteam的TCP/IP socket收集庫。它供給了異步操作,當地cocoa類的基於delegate的完全支撐。重要有以下特征:

  • 隊列的非壅塞的讀和寫,並且可選超時。你可以挪用它讀取和寫入,它會當完成後告訴你。
  • 主動的socket吸收。假如你挪用它吸收銜接,它將為每一個銜接啟動新的實例,固然,也能夠立刻封閉這些銜接。
  • 拜托(delegate)支撐。毛病、銜接、吸收、完全的讀取、完全的寫入、進度和斷開銜接,都可以經由過程拜托形式挪用。
  • 基於run loop的,而不是線程的。固然可以在主線程或許任務線程中應用它,但你不須要如許做。它異步的挪用拜托辦法,應用NSRunLoop。拜托辦法包含socket的參數,可以讓你在多個實例中辨別。
  • 自包括在一個類中。你無需操作流或許socket,這個類幫你做了全體。
  • 支撐基於IPV4和IPV6的TCP流。

AsyncUdpSocket是UDP/IP socket收集庫,包裝自CFSocket。它的任務很像TCP版本,只不外是用於處置UDP的。它包含基於非壅塞隊列的發送吸收操作,完全的拜托支撐,基於runloop,自包括的類,和支撐IPV4和IPV6。

應用AsyncSocket的時刻可以做一層封裝,依據需求供給幾個接口出來。好比:銜接、斷開銜接、發送新聞等等。還有接收新聞,接收到的新聞可以經由過程告訴、署理、block等傳出去。

上面簡略引見一下對AsyncSocket應用.普通來講,一個用戶只須要樹立一個socket長銜接,所以可以用單例類便利應用。

界說單列類:LGSocketServe

LGSocketServe.h

//
//  LGSocketServe.h
//  AsyncSocketDemo
//

#import <Foundation/Foundation.h>
#import "AsyncSocket.h"

@interface LGSocketServe : NSObject<AsyncSocketDelegate>

+ (LGSocketServe *)sharedSocketServe;


@end

LGSocketServe.m

//
//  LGSocketServe.m
//  AsyncSocketDemo
//

#import "LGSocketServe.h"

@implementation LGSocketServe


static LGSocketServe *socketServe = nil;

#pragma mark public static methods


+ (LGSocketServe *)sharedSocketServe {
    @synchronized(self) {
        if(socketServe == nil) {
            socketServe = [[[self class] alloc] init];
        }
    }
    return socketServe;
}


+(id)allocWithZone:(NSZone *)zone
{
    @synchronized(self)
    {
        if (socketServe == nil)
        {
            socketServe = [super allocWithZone:zone];
            return socketServe;
        }
    }
    return nil;
}  


@end

樹立socket長銜接

LGSocketServe.h

@property (nonatomic, strong) AsyncSocket         *socket;       // socket

//  socket銜接
- (void)startConnectSocket;
LGSocketServe.m

//本身設定
#define HOST @"192.168.0.1"
#define PORT 8080

//設置銜接超時
#define TIME_OUT 20

- (void)startConnectSocket
{
    self.socket = [[AsyncSocket alloc] initWithDelegate:self];
    [self.socket setRunLoopModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
    if ( ![self SocketOpen:HOST port:PORT] )
    {

    }

}

- (NSInteger)SocketOpen:(NSString*)addr port:(NSInteger)port
{

    if (![self.socket isConnected])
    {
        NSError *error = nil;
        [self.socket connectToHost:addr onPort:port withTimeout:TIME_OUT error:&error];
    }

    return 0;
}

宏界說一下HOST、PORT、TIME_OUT,完成startConnectSocket辦法。這個時刻要設置一下AsyncSocket的署理AsyncSocketDelegate。當長銜接勝利以後會挪用:

- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
    //這是異步前往的銜接勝利,
    NSLog(@"didConnectToHost");
}

心跳

LGSocketServe.h

@property (nonatomic, retain) NSTimer             *heartTimer;   // 心跳計時器
LGSocketServe.m

- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
    //這是異步前往的銜接勝利,
    NSLog(@"didConnectToHost");

    //經由過程准時器赓續發送新聞,來檢測長銜接
    self.heartTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(checkLongConnectByServe) userInfo:nil repeats:YES];
    [self.heartTimer fire];
}

// 心跳銜接
-(void)checkLongConnectByServe{

    // 向辦事器發送固定可是的新聞,來檢測長銜接
    NSString *longConnect = @"connect is here";
    NSData   *data  = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
    [self.socket writeData:data withTimeout:1 tag:1];
}

在銜接勝利的回調辦法裡,啟動准時器,每隔2秒向辦事器發送固定的新聞來檢測長銜接。(這個依據辦事器的須要便可以了)

斷開銜接

1,用戶手動斷開銜接

LGSocketServe.h

// 斷開socket銜接
-(void)cutOffSocket;
LGSocketServe.m

-(void)cutOffSocket
{
    self.socket.userData = SocketOfflineByUser;
    [self.socket disconnect];
}

cutOffSocket是用戶斷開銜接以後,不在測驗考試從新銜接。

2,wifi斷開,socket斷開銜接

LGSocketServe.m

- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
{

    NSLog(@" willDisconnectWithError %ld   err = %@",sock.userData,[err description]);
    if (err.code == 57) {
        self.socket.userData = SocketOfflineByWifiCut;
    }

}

wifi斷開以後,會回調onSocket:willDisconnectWithError:辦法,err.code == 57,這個時刻設置self.socket.userData = SocketOfflineByWifiCut。

從新銜接

socket斷開以後會回調:

LGSocketServe.m

- (void)onSocketDidDisconnect:(AsyncSocket *)sock
{

    NSLog(@"7878 sorry the connect is failure %ld",sock.userData);

    if (sock.userData == SocketOfflineByServer) {
        // 辦事器失落線,重連
        [self startConnectSocket];
    }
    else if (sock.userData == SocketOfflineByUser) {

        // 假如由用戶斷開,不停止重連
        return;
    }else if (sock.userData == SocketOfflineByWifiCut) {

        // wifi斷開,不停止重連
        return;
    }

}

在onSocketDidDisconnect回調辦法外面,會依據self.socket.userData來斷定能否須要從新銜接。

發送新聞

LGSocketServe.h

// 發送新聞
- (void)sendMessage:(id)message;
LGSocketServe.m

//設置寫入超時 -1 表現不會應用超時
#define WRITE_TIME_OUT -1

- (void)sendMessage:(id)message
{
    //像辦事器發送數據
    NSData *cmdData = [message dataUsingEncoding:NSUTF8StringEncoding];
    [self.socket writeData:cmdData withTimeout:WRITE_TIME_OUT tag:1];
}

//發送新聞勝利以後回調
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithtag:(long)tag
{

}

發送新聞勝利以後會挪用onSocket:didWriteDataWithtag:,在這個辦法裡可以停止讀撤消息。

接收新聞

LGSocketServe.m

//設置讀取超時 -1 表現不會應用超時
#define READ_TIME_OUT -1

#define MAX_BUFFER 1024

//發送新聞勝利以後回調
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithtag:(long)tag
{
    //讀撤消息
    [self.socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];
}

//接收新聞勝利以後回調
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    //辦事端前往新聞數據量比擬年夜時,能夠分屢次前往。所以在讀撤消息的時刻,設置MAX_BUFFER表現每次最多讀取若干,當data.length < MAX_BUFFER我們以為有能夠是接收完一個完全的新聞,然後才解析
    if( data.length < MAX_BUFFER )
    {
        //收到成果解析...
        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
        NSLog(@"%@",dic);
        //解析出來的新聞,可以經由過程告訴、署理、block等傳出去

    }


    [self.socket readDataWithTimeout:READ_TIME_OUT buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];

接收新聞後去解析,然後可以經由過程告訴、署理、block等傳出去。在onSocket:didReadData:withTag:回調辦法外面須要赓續讀撤消息,由於數據量比擬年夜的話,辦事器會分屢次前往。所以我們須要界說一個MAX_BUFFER的宏,表現每次最多讀取若干。當data.length < MAX_BUFFER我們以為有能夠是接收完一個完全的新聞,然後才解析 。

失足處置

LGSocketServe.m

- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
{
    NSData * unreadData = [sock unreadData]; // ** This gets the current buffer
    if(unreadData.length > 0) {
        [self onSocket:sock didReadData:unreadData withTag:0]; // ** Return as much data that could be collected
    } else {

        NSLog(@" willDisconnectWithError %ld   err = %@",sock.userData,[err description]);
        if (err.code == 57) {
            self.socket.userData = SocketOfflineByWifiCut;
        }
    }

}

socket失足會回調onSocket:willDisconnectWithError:辦法,可以經由過程unreadData來讀取將來得及讀取的buffer。

應用

導入#import “LGSocketServe.h”

 LGSocketServe *socketServe = [LGSocketServe sharedSocketServe];
//socket銜接前先斷開銜接以避免之前socket銜接沒有斷勸導致閃退
[socketServe cutOffSocket];
socketServe.socket.userData = SocketOfflineByServer;
[socketServe startConnectSocket];

//發送新聞 @"hello world"只是舉個列子,詳細依據辦事真個新聞格局
[socketServe sendMessage:@"hello world"];

【iOS運用中應用AsyncSocket庫處置Socket通訊的用法講授】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved