CocoaAsyncSocket使用详解

来源:互联网 发布:windows未能启动成功 编辑:程序博客网 时间:2024/03/29 21:35

CocoaAsyncSocket网络通信使用之tcp连接(一)

简述:

在互联网世界中,网络访问是必不可少的一部分,而对于程序员来说,网络编程却是一个比较复杂的存在,特别是socket处理方面。

在android平台中,java类库丰富,封装良好,比如:mina,netty等等。

而在ios平台中,也有出名的socket库,CocoaAsyncSocket


最近碰到一些朋友在socket的应用上一直不是特别熟悉,自己在接触过socket底层库,使用过mina,netty和CocoaAsyncSocket后,

也想整理一份自己的工具库,于是有如下内容。


CocoaAsyncSocket的功能强大,有tcp和udp两部分,这里只学习整理tcp部分。


建立ios工程:

首先建立一个ios工程,RHSocketDemo. (本例使用pod管理类库,如果不熟悉,可以先看前面的文章:CocoaPods安装和使用教程)

然后在工程目录下建立Podfile文件,内容如下:

platform:ios,'7.0'

pod 'CocoaAsyncSocket', '~> 7.4.1'


然后使用pod instatll —no-repo-update命令,生成工程管理文件。

关闭原先的工程,使用新生成的RHSocketDemo.xcworkspace文件开启工程。


以上是通过pod引入CocoaAsyncSocket库,省去了加入framework的步骤,,比较方便。

也可以下载CocoaAsyncSocket源码,然后将源码加入到工程中,但是需要额外手动加入framework。


构造自己的socket连接类:

1-为了简化类库中的内容,隐藏一些不关心的接口方法。

2-对类库做一层封装隔离,以个人习惯的方式呈现使用(可以方便库的更新替换,比如:asi到afn的http 库迁移)

基于以上两个原因,我们使用CocoaAsyncSocket封装自己的sokcet connection类。代码如下:


RHSocketConfig.h文件:

[objc] view plaincopy
  1. #ifndef RHSocketDemo_RHSocketConfig_h  
  2. #define RHSocketDemo_RHSocketConfig_h  
  3.   
  4. #ifdef DEBUG  
  5. #define RHSocketDebug  
  6. #endif  
  7.   
  8. #ifdef RHSocketDebug  
  9. #define RHSocketLog(format, ...) NSLog(format, ## __VA_ARGS__)  
  10. #else  
  11. #define RHSocketLog(format, ...)  
  12. #endif  
  13.   
  14. #endif  

RHSocketConnection.h文件:

[objc] view plaincopy
  1. #import <Foundation/Foundation.h>  
  2. #import "RHSocketConfig.h"  
  3.   
  4. @protocol RHSocketConnectionDelegate <NSObject>  
  5.   
  6. - (void)didDisconnectWithError:(NSError *)error;  
  7. - (void)didConnectToHost:(NSString *)host port:(UInt16)port;  
  8. - (void)didReceiveData:(NSData *)data tag:(long)tag;  
  9.   
  10. @end  
  11.   
  12. @interface RHSocketConnection : NSObject  
  13.   
  14. @property (nonatomic, weak) id<RHSocketConnectionDelegate> delegate;  
  15.   
  16. - (void)connectWithHost:(NSString *)hostName port:(int)port;  
  17. - (void)disconnect;  
  18.   
  19. - (BOOL)isConnected;  
  20. - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag;  
  21. - (void)writeData:(NSData *)data timeout:(NSTimeInterval)timeout tag:(long)tag;  
  22.   
  23. @end  

RHSocketConnection.m文件:

[objc] view plaincopy
  1. #import "RHSocketConnection.h"  
  2. #import "GCDAsyncSocket.h"  
  3.   
  4. @interface RHSocketConnection () <GCDAsyncSocketDelegate>  
  5. {  
  6.     GCDAsyncSocket *_asyncSocket;  
  7. }  
  8.   
  9. @end  
  10.   
  11. @implementation RHSocketConnection  
  12.   
  13. - (instancetype)init  
  14. {  
  15.     if (self = [super init]) {  
  16.         _asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];  
  17.     }  
  18.     return self;  
  19. }  
  20.   
  21. - (void)dealloc  
  22. {  
  23.     _asyncSocket.delegate = nil;  
  24.     _asyncSocket = nil;  
  25. }  
  26.   
  27. - (void)connectWithHost:(NSString *)hostName port:(int)port  
  28. {  
  29.     NSError *error = nil;  
  30.     [_asyncSocket connectToHost:hostName onPort:port error:&error];  
  31.     if (error) {  
  32.         RHSocketLog(@"[RHSocketConnection] connectWithHost error: %@", error.description);  
  33.         if (_delegate && [_delegate respondsToSelector:@selector(didDisconnectWithError:)]) {  
  34.             [_delegate didDisconnectWithError:error];  
  35.         }  
  36.     }  
  37. }  
  38.   
  39. - (void)disconnect  
  40. {  
  41.     [_asyncSocket disconnect];  
  42. }  
  43.   
  44. - (BOOL)isConnected  
  45. {  
  46.     return [_asyncSocket isConnected];  
  47. }  
  48.   
  49. - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag  
  50. {  
  51.     [_asyncSocket readDataWithTimeout:timeout tag:tag];  
  52. }  
  53.   
  54. - (void)writeData:(NSData *)data timeout:(NSTimeInterval)timeout tag:(long)tag  
  55. {  
  56.     [_asyncSocket writeData:data withTimeout:timeout tag:tag];  
  57. }  
  58.   
  59. #pragma mark -  
  60. #pragma mark GCDAsyncSocketDelegate method  
  61.   
  62. - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err  
  63. {  
  64.     RHSocketLog(@"[RHSocketConnection] didDisconnect...%@", err.description);  
  65.     if (_delegate && [_delegate respondsToSelector:@selector(didDisconnectWithError:)]) {  
  66.         [_delegate didDisconnectWithError:err];  
  67.     }  
  68. }  
  69.   
  70. - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port  
  71. {  
  72.     RHSocketLog(@"[RHSocketConnection] didConnectToHost: %@, port: %d", host, port);  
  73.     if (_delegate && [_delegate respondsToSelector:@selector(didConnectToHost:port:)]) {  
  74.         [_delegate didConnectToHost:host port:port];  
  75.     }  
  76. }  
  77.   
  78. - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag  
  79. {  
  80.     RHSocketLog(@"[RHSocketConnection] didReadData length: %lu, tag: %ld", (unsigned long)data.length, tag);  
  81.     if (_delegate && [_delegate respondsToSelector:@selector(didReceiveData:tag:)]) {  
  82.         [_delegate didReceiveData:data tag:tag];  
  83.     }  
  84.     [sock readDataWithTimeout:-1 tag:tag];  
  85. }  
  86.   
  87. - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag  
  88. {  
  89.     RHSocketLog(@"[RHSocketConnection] didWriteDataWithTag: %ld", tag);  
  90.     [sock readDataWithTimeout:-1 tag:tag];  
  91. }  
  92.   
  93. @end  

测试调用的ViewController.m文件:

[objc] view plaincopy
  1. #import "ViewController.h"  
  2. #import "RHSocketConnection.h"  
  3.   
  4. @interface ViewController () <RHSocketConnectionDelegate>  
  5. {  
  6.     NSString *_serverHost;  
  7.     int _serverPort;  
  8.     RHSocketConnection *_connection;  
  9. }  
  10.   
  11. @end  
  12.   
  13. @implementation ViewController  
  14.   
  15. - (void)viewDidLoad {  
  16.     [super viewDidLoad];  
  17.   
  18.     // Do any additional setup after loading the view, typically from a nib.  
  19.   
  20.     _serverHost = @"www.baidu.com";  
  21.     _serverPort = 80;  
  22.     [self openConnection];  
  23. }  
  24.   
  25. #pragma mark -  
  26. #pragma mark RHSocketConnection method  
  27.   
  28. - (void)openConnection  
  29. {  
  30.     [self closeConnection];  
  31.     _connection = [[RHSocketConnection alloc] init];  
  32.     _connection.delegate = self;  
  33.     [_connection connectWithHost:_serverHost port:_serverPort];  
  34. }  
  35.   
  36. - (void)closeConnection  
  37. {  
  38.     if (_connection) {  
  39.         _connection.delegate = nil;  
  40.         [_connection disconnect];  
  41.         _connection = nil;  
  42.     }  
  43. }  
  44.   
  45. #pragma mark -  
  46. #pragma mark RHSocketConnectionDelegate method  
  47.   
  48. - (void)didDisconnectWithError:(NSError *)error  
  49. {  
  50.     RHSocketLog(@"didDisconnectWithError...");  
  51. }  
  52.   
  53. - (void)didConnectToHost:(NSString *)host port:(UInt16)port  
  54. {  
  55.     RHSocketLog(@"didConnectToHost...");  
  56. }  
  57.   
  58. - (void)didReceiveData:(NSData *)data tag:(long)tag  
  59. {  
  60.     RHSocketLog(@"didReceiveData...");  
  61. }  
  62.   
  63. @end  

上面的代码中,RHSocketConnection负责网络的连接,ViewController负责测试代码。

连接成功后,会输出:[RHSocketConnection] didConnectToHost: 115.239.210.27, port: 80


以下是测试调用的主要方法:

[objc] view plaincopy
  1. NSString *serverHost = @"www.baidu.com";  
  2. int serverPort = 80;  
  3. RHSocketConnection *connection = [[RHSocketConnection alloc] init];  
  4. [connection connectWithHost:serverHost port:serverPort];  


总结:

本篇主要是封装一个socket connection。然后访问baidu的首页,校验连接是否成功。

而tcp的麻烦之处主要在自定义协议上,而自定义协议导致代码共用性的下降。

怎么提升代码的共用性是本文的出发点,下一篇,我们引入编码器和解码器,

来构建一个基本的socket tcp框架,提升代码的共用性。


------------------------

转载请注明出处,谢谢

email: zhu410289616@163.com

qq: 410289616

qq群:330585393


0 0