最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

iOS應(yīng)用中使用AsyncSocket庫(kù)處理Socket通信的用法講解

 更新時(shí)間:2016年05月11日 09:17:53   作者:李剛  
這篇文章主要介紹了iOS應(yīng)用中使用AsyncSocket庫(kù)處理Socket通信的用法講解,AsyncSocket同時(shí)支持TCP和UDP,文中展示了其建立斷開連接及發(fā)送接收消息的操作,very好用,需要的朋友可以參考下

用socket可以實(shí)現(xiàn)像QQ那樣發(fā)送即時(shí)消息的功能。客戶端和服務(wù)端需要建立長(zhǎng)連接,在長(zhǎng)連接的情況下,發(fā)送消息。客戶端可以發(fā)送心跳包來(lái)檢測(cè)長(zhǎng)連接。

在iOS開發(fā)中使用socket,一般都是用第三方庫(kù)AsyncSocket,不得不承認(rèn)這個(gè)庫(kù)確實(shí)很強(qiáng)大。下載地址CocoaAsyncSocket
。

特性

AsyncSocket類是支持TCP的。
AsyncUdpSocket是支持UDP的。
AsyncSocket是封裝了CFSocket和CFSteam的TCP/IP socket網(wǎng)絡(luò)庫(kù)。它提供了異步操作,本地cocoa類的基于delegate的完整支持。主要有以下特性:

  • 隊(duì)列的非阻塞的讀和寫,而且可選超時(shí)。你可以調(diào)用它讀取和寫入,它會(huì)當(dāng)完成后告知你。
  • 自動(dòng)的socket接收。如果你調(diào)用它接收連接,它將為每個(gè)連接啟動(dòng)新的實(shí)例,當(dāng)然,也可以立即關(guān)閉這些連接。
  • 委托(delegate)支持。錯(cuò)誤、連接、接收、完整的讀取、完整的寫入、進(jìn)度以及斷開連接,都可以通過(guò)委托模式調(diào)用。
  • 基于run loop的,而不是線程的。雖然可以在主線程或者工作線程中使用它,但你不需要這樣做。它異步的調(diào)用委托方法,使用NSRunLoop。委托方法包括socket的參數(shù),可讓你在多個(gè)實(shí)例中區(qū)分。
  • 自包含在一個(gè)類中。你無(wú)需操作流或者socket,這個(gè)類幫你做了全部。
  • 支持基于IPV4和IPV6的TCP流。

AsyncUdpSocket是UDP/IP socket網(wǎng)絡(luò)庫(kù),包裝自CFSocket。它的工作很像TCP版本,只不過(guò)是用于處理UDP的。它包括基于非阻塞隊(duì)列的發(fā)送接收操作,完整的委托支持,基于runloop,自包含的類,以及支持IPV4和IPV6。

使用AsyncSocket的時(shí)候可以做一層封裝,根據(jù)需求提供幾個(gè)接口出來(lái)。比如:連接、斷開連接、發(fā)送消息等等。還有接受消息,接受到的消息可以通過(guò)通知、代理、block等傳出去。

下面簡(jiǎn)單介紹一下對(duì)AsyncSocket使用.一般來(lái)說(shuō),一個(gè)用戶只需要建立一個(gè)socket長(zhǎng)連接,所以可以用單例類方便使用。

定義單列類:LGSocketServe

LGSocketServe.h

復(fù)制代碼 代碼如下:

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

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

@interface LGSocketServe : NSObject<AsyncSocketDelegate>

+ (LGSocketServe *)sharedSocketServe;


@end


LGSocketServe.m
復(fù)制代碼 代碼如下:

//
//  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長(zhǎng)連接

LGSocketServe.h

復(fù)制代碼 代碼如下:

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

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

//自己設(shè)定
#define HOST @"192.168.0.1"
#define PORT 8080

//設(shè)置連接超時(shí)
#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,實(shí)現(xiàn)startConnectSocket方法。這個(gè)時(shí)候要設(shè)置一下AsyncSocket的代理AsyncSocketDelegate。當(dāng)長(zhǎng)連接成功之后會(huì)調(diào)用:
復(fù)制代碼 代碼如下:

- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
    //這是異步返回的連接成功,
    NSLog(@"didConnectToHost");
}

心跳

LGSocketServe.h

復(fù)制代碼 代碼如下:

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

- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
    //這是異步返回的連接成功,
    NSLog(@"didConnectToHost");

    //通過(guò)定時(shí)器不斷發(fā)送消息,來(lái)檢測(cè)長(zhǎng)連接
    self.heartTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(checkLongConnectByServe) userInfo:nil repeats:YES];
    [self.heartTimer fire];
}

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

    // 向服務(wù)器發(fā)送固定可是的消息,來(lái)檢測(cè)長(zhǎng)連接
    NSString *longConnect = @"connect is here";
    NSData   *data  = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
    [self.socket writeData:data withTimeout:1 tag:1];
}


在連接成功的回調(diào)方法里,啟動(dòng)定時(shí)器,每隔2秒向服務(wù)器發(fā)送固定的消息來(lái)檢測(cè)長(zhǎng)連接。(這個(gè)根據(jù)服務(wù)器的需要就可以了)

斷開連接

1,用戶手動(dòng)斷開連接

LGSocketServe.h

復(fù)制代碼 代碼如下:

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

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


cutOffSocket是用戶斷開連接之后,不在嘗試重新連接。

2,wifi斷開,socket斷開連接

LGSocketServe.m

復(fù)制代碼 代碼如下:

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

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

}


wifi斷開之后,會(huì)回調(diào)onSocket:willDisconnectWithError:方法,err.code == 57,這個(gè)時(shí)候設(shè)置self.socket.userData = SocketOfflineByWifiCut。

重新連接

socket斷開之后會(huì)回調(diào):

LGSocketServe.m

復(fù)制代碼 代碼如下:

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

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

    if (sock.userData == SocketOfflineByServer) {
        // 服務(wù)器掉線,重連
        [self startConnectSocket];
    }
    else if (sock.userData == SocketOfflineByUser) {

        // 如果由用戶斷開,不進(jìn)行重連
        return;
    }else if (sock.userData == SocketOfflineByWifiCut) {

        // wifi斷開,不進(jìn)行重連
        return;
    }

}


在onSocketDidDisconnect回調(diào)方法里面,會(huì)根據(jù)self.socket.userData來(lái)判斷是否需要重新連接。

發(fā)送消息

LGSocketServe.h

復(fù)制代碼 代碼如下:

// 發(fā)送消息
- (void)sendMessage:(id)message;
LGSocketServe.m

//設(shè)置寫入超時(shí) -1 表示不會(huì)使用超時(shí)
#define WRITE_TIME_OUT -1

- (void)sendMessage:(id)message
{
    //像服務(wù)器發(fā)送數(shù)據(jù)
    NSData *cmdData = [message dataUsingEncoding:NSUTF8StringEncoding];
    [self.socket writeData:cmdData withTimeout:WRITE_TIME_OUT tag:1];
}

//發(fā)送消息成功之后回調(diào)
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
{

}


發(fā)送消息成功之后會(huì)調(diào)用onSocket:didWriteDataWithTag:,在這個(gè)方法里可以進(jìn)行讀取消息。

接受消息

LGSocketServe.m

復(fù)制代碼 代碼如下:

//設(shè)置讀取超時(shí) -1 表示不會(huì)使用超時(shí)
#define READ_TIME_OUT -1

#define MAX_BUFFER 1024

//發(fā)送消息成功之后回調(diào)
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    //讀取消息
    [self.socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];
}

//接受消息成功之后回調(diào)
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    //服務(wù)端返回消息數(shù)據(jù)量比較大時(shí),可能分多次返回。所以在讀取消息的時(shí)候,設(shè)置MAX_BUFFER表示每次最多讀取多少,當(dāng)data.length < MAX_BUFFER我們認(rèn)為有可能是接受完一個(gè)完整的消息,然后才解析
    if( data.length < MAX_BUFFER )
    {
        //收到結(jié)果解析...
        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
        NSLog(@"%@",dic);
        //解析出來(lái)的消息,可以通過(guò)通知、代理、block等傳出去

    }


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


接受消息后去解析,然后可以通過(guò)通知、代理、block等傳出去。在onSocket:didReadData:withTag:回調(diào)方法里面需要不斷讀取消息,因?yàn)閿?shù)據(jù)量比較大的話,服務(wù)器會(huì)分多次返回。所以我們需要定義一個(gè)MAX_BUFFER的宏,表示每次最多讀取多少。當(dāng)data.length < MAX_BUFFER我們認(rèn)為有可能是接受完一個(gè)完整的消息,然后才解析 。

出錯(cuò)處理

LGSocketServe.m

復(fù)制代碼 代碼如下:

- (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出錯(cuò)會(huì)回調(diào)onSocket:willDisconnectWithError:方法,可以通過(guò)unreadData來(lái)讀取未來(lái)得及讀取的buffer。

使用

導(dǎo)入#import “LGSocketServe.h”

復(fù)制代碼 代碼如下:

 LGSocketServe *socketServe = [LGSocketServe sharedSocketServe];
//socket連接前先斷開連接以免之前socket連接沒(méi)有斷開導(dǎo)致閃退
[socketServe cutOffSocket];
socketServe.socket.userData = SocketOfflineByServer;
[socketServe startConnectSocket];

//發(fā)送消息 @"hello world"只是舉個(gè)列子,具體根據(jù)服務(wù)端的消息格式
[socketServe sendMessage:@"hello world"];

相關(guān)文章

  • IOS10 隱私權(quán)限設(shè)置實(shí)例詳解

    IOS10 隱私權(quán)限設(shè)置實(shí)例詳解

    這篇文章主要介紹了IOS10 隱私權(quán)限設(shè)置實(shí)例詳解的相關(guān)資料,本文主要是介紹,在使用相機(jī)功能是遇到錯(cuò)誤,這里說(shuō)明該如何解決,需要的朋友可以參考下
    2016-12-12
  • iOS中searchBar(搜索框)光標(biāo)初始位置后移

    iOS中searchBar(搜索框)光標(biāo)初始位置后移

    這篇文章主要介紹了iOS中searchBar(搜索框)光標(biāo)初始位置后移的關(guān)鍵代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-08-08
  • iOS使用UICollectionView實(shí)現(xiàn)列表頭部拉伸效果

    iOS使用UICollectionView實(shí)現(xiàn)列表頭部拉伸效果

    這篇文章主要介紹了iOS使用UICollectionView實(shí)現(xiàn)列表頭部拉伸效果,OC和Swift兩個(gè)版本,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • iOS 11 下適配UITableView 問(wèn)題

    iOS 11 下適配UITableView 問(wèn)題

    這篇文章主要介紹了iOS 11 下適配UITableView 問(wèn)題,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-09-09
  • Unity iOS混合開發(fā)界面切換思路解析

    Unity iOS混合開發(fā)界面切換思路解析

    這篇文章主要介紹了Unity iOS混合開發(fā)界面切換思路解析的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • 快速上手IOS UIBezierPath(貝塞爾曲線)

    快速上手IOS UIBezierPath(貝塞爾曲線)

    本文主要介紹了IOS 貝塞爾曲線(UIBezierPath)的基礎(chǔ)知識(shí)。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧
    2017-03-03
  • IOS實(shí)現(xiàn)微信授權(quán)登錄功能

    IOS實(shí)現(xiàn)微信授權(quán)登錄功能

    微信是一個(gè)在開發(fā)中經(jīng)常會(huì)使用到的平臺(tái),比如微信登錄、授權(quán)、支付、分享。今天我們來(lái)看看如何在自己的應(yīng)用里面集成微信授權(quán),需要的朋友參考下吧
    2017-03-03
  • IOS 開發(fā)之實(shí)現(xiàn)取消tableView返回時(shí)cell選中的問(wèn)題

    IOS 開發(fā)之實(shí)現(xiàn)取消tableView返回時(shí)cell選中的問(wèn)題

    這篇文章主要介紹了IOS 開發(fā)之實(shí)現(xiàn)取消tableView返回時(shí)cell選中的問(wèn)題的相關(guān)資料,希望通過(guò)本文能實(shí)現(xiàn)大家想要的功能,需要的朋友可以參考下
    2017-09-09
  • 詳解IOS點(diǎn)擊空白處隱藏鍵盤的幾種方法介紹

    詳解IOS點(diǎn)擊空白處隱藏鍵盤的幾種方法介紹

    本篇文章主要介紹了IOS點(diǎn)擊空白處隱藏鍵盤的幾種方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。
    2016-12-12
  • Objective-C?入門篇(推薦)

    Objective-C?入門篇(推薦)

    由C語(yǔ)言和Smalltalk擴(kuò)展出來(lái)的,是C語(yǔ)言的超集,最大的區(qū)別是OC是面向?qū)ο蟮?,其火星文寫法?duì)于之前從事Java開發(fā)的同學(xué)頗感蛋疼,OC最大特點(diǎn)之一是使用消息結(jié)構(gòu)而不是函數(shù)調(diào)用
    2021-11-11

最新評(píng)論

清远市| 淮阳县| 利川市| 莱州市| 霍山县| 阳原县| 兴海县| 太仓市| 剑阁县| 桃园县| 循化| 泸定县| 承德市| 平遥县| 宜州市| 凤山市| 山东| 乌苏市| 辉南县| 新巴尔虎左旗| 双柏县| 儋州市| 福贡县| 三台县| 仙居县| 喀喇沁旗| 九江县| 平阳县| 漠河县| 朝阳县| 梁平县| 乌海市| 永年县| 北海市| 增城市| 泰顺县| 河池市| 元氏县| 合川市| 静宁县| 崇义县|