之前一直没做过socket相关的项目,在智能家居领域socket应用还是比较广泛的,所以一直想着学习socket相关知识,正好最近项目不是很忙,就想着补一补之前要学但是没学的东西。
-
iOS里的socket主要是基于
CFSocket
来做的,原生socket是用c语言写的,调用的方式有点复杂,所以一般很少会用到,可以看这个链接了解一下即可 -
这里主要说一下对原生
CFSocket
进行封装过的第三方库GCDAsyncSocket
,这个库应用还是比较广泛的,github上的star数量达到了11.8k。(在github上要搜索CocoaAsyncSocket
才能搜到,直接搜GCDAsyncSocket
的话搜到的都是各种demo) -
GCDAsyncSocket
的简单使用,直接把GCDAsyncSocket.h
和GCDAsyncSocket.m
复制进项目即可使用 -
Server代码:
//初始化 self.connectedSockets = [[NSMutableArray alloc] initWithCapacity:1]; self.serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; //开始监听端口 [self.serverSocket acceptOnPort:port error:&error];
#pragma mark - GCDAsyncSocketDelegate //有客户端连接时会调用 - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket { NSLog(@"%s", __func__); //保持对newSocket的引用,使用newSocket来发送和读取数据,newSocket和sock有相同的代理 //下面几个代理方法中的sock即为此处的newSocket [self.connectedSockets addObject:newSocket]; NSData *data = [@"欢迎连接!" dataUsingEncoding:NSUTF8StringEncoding]; [newSocket writeData:data withTimeout:-1 tag:0]; } //写入数据完成回调 - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag { NSLog(@"%s", __func__); [sock readDataWithTimeout:-1 tag:tag]; } //读取数据完成回调 - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { NSLog(@"%s", __func__); NSString *message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"string: %@", message); NSString *sendString = [@"你说:" stringByAppendingString:message]; NSData *sendData = [sendString dataUsingEncoding:NSUTF8StringEncoding]; [sock writeData:sendData withTimeout:-1 tag:tag]; }
在调试过程中遇到的问题: 1. 没有设置`delegatequeue`报错,初始化时设置为`dispatch_get_main_queue`即可 2. 客户端发来的数据没有读取到,需要显示的调用`readDataWithTimeout`方法来读取数据
-
Client代码:
//初始化 self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; //开始连接 NSError *error; [self.clientSocket connectToHost:hostIP onPort:hostPort.integerValue error:&error];
#pragma mark - GCDAsyncSocketDelegate //成功连接到服务器 - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port { NSLog(@"%s", __func__); NSData *data = [@"已经连接!" dataUsingEncoding:NSUTF8StringEncoding]; [sock writeData:data withTimeout:-1 tag:0]; } //写入数据完成 - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag { NSLog(@"%s", __func__); [sock readDataWithTimeout:-1 tag:tag]; } //读取数据完成 - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { NSLog(@"%s", __func__); NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"string: %@", string); [sock readDataWithTimeout:-1 tag:0]; }
在调试过程中遇到的问题: 1. 收到的数据不是最新的,而是上一次发的数据,需要在`didReadData`方法的最后,再调用`readDataWithTimeout`即可
-
用到的调试工具
刚开始连接运行两个demo,分别在手机和电脑上测试,一直连不上,不知道什么问题,百度之后发现了sockit这个调试工具。使用homebrew安装,就可以在mac上调试socket,可以分别模拟客户端和服务端进行调试,非常方便。