IOS Socket 04-利用架構CocoaAsyncSocket實現用戶端/伺服器端

來源:互聯網
上載者:User

標籤:

 

  這篇文章,我們介紹CocoaAsyncSocket架構的使用,主要介紹實現用戶端/伺服器端代碼,相信在網上已經很多這樣的文章了,這裡做一下自己的總結。這裡介紹使用GCD方式

 

一.用戶端

1.

讀者可以在github下載架構源碼 https://github.com/robbiehanson/CocoaAsyncSocket

下載後,可以看到在Examples下面可以看到很多例子,如果讀者自學能力高,可以略過下面的文章。

 

2.開始使用

1)在 \Source\GCD 目錄下,我們可以看到GCDAsyncSocket的h與m檔案,我們複製這兩個檔案到項目中。

2)我們在代碼裡面匯入標頭檔 #import "GCDAsyncSocket.h" 與 協議 GCDAsyncSocketDelegate。

 

3.代碼

1)定義全域變數 GCDAsyncSocket *_socket;

2)開始串連伺服器

- (void) connect2Server() {    //1.主機與連接埠號碼    NSString *host = @"127.0.0.1";    int port = 12345;        //初始化socket,這裡有兩種方式。分別為是主/子線程中運行socket。根據項目不同而定    _socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];//這種是在主線程中運行    //_socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; 這種是在子線程中運行        //開始串連    NSError *error = nil;    [_socket connectToHost:host onPort port error:&error];    if(error) {        NSLog("error:%@", error);    }    }

3)登入

-(void)login() {    //登入String    NSString *loginStr = "iam:I am login!";    NSData *loginData = [loginStr dataUsingEncoding: NSUTF8StringEncoding];    //發送登入指令。-1表示不逾時。tag200表示這個指令的標識,很大用處    [_socket writeData: loginData withTimeout:-1 tag:200];}

4)開始聊天

//發送聊天資料-(void) sendMsg: (NSString*)msg{    NSString *sendMsg = [@"msg:I send message to u!"];    NSData *sendData = [sendMsg dataUsingEncoding: NSUTF8StringEncoding];    [_socket writeData; sendData withTimeout:-1 tag:201];}

5)實現協議delegate

#pragma mark -socket的代理#pragma mark 串連成功-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{       //串連成功    NSLog(@"%s",__func__);}#pragma mark 中斷連線-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{    if (err) {         NSLog(@"串連失敗");    }else{        NSLog(@"正常斷開");      }}#pragma mark 資料發送成功-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{      NSLog(@"%s",__func__);     //發送完資料手動讀取     [sock readDataWithTimeout:-1 tag:tag];}#pragma mark 讀取資料-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{        //代理是在主/子線程調用    NSLog(@"%@",[NSThread currentThread]);    NSString *receiverStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];        if (tag == 200) {    //登入指令     }else if(tag == 201){    //聊天資料    }        NSLog(@"%s %@",__func__,receiverStr);}

 

 

二.伺服器端

伺服器端不可能在iphone/ipad上運行,所以我們建立一個單純命令列的項目。

1.建立一個類MyChatServer,並且開放公用方法startServer,標頭檔如下

#import <Foundation/Foundation.h>@interface MyChatServer : NSObject/** *  開啟聊天伺服器 */-(void)startServer;@end

2.在main檔案中,開啟聊天伺服器,並且開啟主運行迴圈,讓伺服器接收到用戶端請求

//實現聊天MyChatServer *chatServer = [[MyChatServer alloc] init];[chatServer startServer];//開啟主運行迴圈[[NSRunLoop currentRunLoop] run];

3.在MychatServer.m檔案中,我們開始實現GCDAsyncSocket的方法(下面代碼都在MychatServer.m中)

1)首先建一個成員變數array對象,把所有的socket(用戶端)對象儲存在裡面

@property(strong,nonatomic)NSMutableArray *clientSocket;

私人變數serverSocket與golbal_queue

GCDAsyncSocket *_serverSocket;dispatch_queue_t _golbalQueue;

2)在類初始化的時候,我們初始化私人變數與成員變數

-(instancetype)init{    if (self = [super init]) {      _clientSocket = [NSMutableArray array];          //建立全域queue      _golbalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);      //建立服務端的socket,注意這裡的是初始化的同時已經指定了delegate      _serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:_golbalQueue];    }     return self;}

3)開啟伺服器聊天startServer

-(void)startChatServer{       //開啟監聽連接埠
    NSError *err;    [_serverSocket acceptOnPort:12345 error:&err];     if (!err) {        NSLog(@"服務開啟成功");    }else{        NSLog(@"服務開啟失敗");    }}

4)實現delegate

#pragma mark 有用戶端建立串連的時候調用-(void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{    //sock為服務端的socket,服務端的socket只負責用戶端的串連,不負責資料的讀取。   newSocket為用戶端的socket
    NSLog(@"服務端的socket %p 用戶端的socket %p",sock,newSocket);    //儲存用戶端的socket,如果不儲存,伺服器會自動斷開與用戶端的串連(用戶端那邊會報中斷連線的log)    NSLog(@"%s",__func__);    [self.clientSocket addObject:newSocket];        //newSocket為用戶端的Socket。這裡讀取資料    [newSocket readDataWithTimeout:-1 tag:100];}#pragma mark 伺服器寫資料給用戶端-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{    NSLog(@"%s",__func__);    [sock readDataWithTimeout:-1 tag:100];}#pragma mark 接收用戶端傳遞過來的資料-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{    //sock為用戶端的socket     NSLog(@"用戶端的socket %p",sock);    //接收到資料    NSString *receiverStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];    NSLog(@"length:%ld",receiverStr.length);    // 把斷行符號和換行字元去掉,接收到的字串有時候包括這2個,導致判斷quit指令的時候判斷不相等    receiverStr = [receiverStr stringByReplacingOccurrencesOfString:@"\r" withString:@""];    receiverStr = [receiverStr stringByReplacingOccurrencesOfString:@"\n" withString:@""];        //判斷是登入指令還是發送聊天資料的指令。這些指令都是自訂的    //登入指令    if([receiverStr hasPrefix:@"iam:"]){
        // 擷取使用者名稱        NSString *user = [receiverStr componentsSeparatedByString:@":"][1];        // 響應給用戶端的資料        NSString *respStr = [user stringByAppendingString:@"has joined"];      [sock writeData:[respStr dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];    }    //聊天指令    if ([receiverStr hasPrefix:@"msg:"]) {        //截取聊天訊息        NSString *msg = [receiverStr componentsSeparatedByString:@":"][1];      [sock writeData:[msg dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];    }    //quit指令    if ([receiverStr isEqualToString:@"quit"]) {        //中斷連線        [sock disconnect];        //移除socket       [self.clientSocket removeObject:sock];     }    NSLog(@"%s",__func__);}

 

查看本文章之前,可以看看

IOS Socket 03-建立串連與登入

IOS Socket 04-利用架構CocoaAsyncSocket實現用戶端/伺服器端

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.