iOS网络编程之TCP/IP应用篇(二)-框架的二次封装
上篇文章贴出了头文件的定义,现在来逐一实现和说明。
uint8_t m_pBuffer[SOCKET_TCP_BUFFER] 和int m_nBufferLen
SOCKET_TCP_BUFFER 宏定义16384,m_pBuffer为总长度为16384个字节的数组,为网络缓冲区,保存socket接收的字节流。
m_nBufferLen 准确的说是一个标识位,记录缓冲区的数据的长度(这个变量在解析缓冲区数据时要用到)。
id<SocketDelegate> delegate 解析数据完成后进行分发的接口(在第三篇中会详细说明)。
AsyncSocket*m_pSocket 保存第三方封装socket的实例。
一,初始化api,这个实现很简单,对变量进行初始化,初始化后我们就有了可以调用的socket(m_pSocket)
/**创建*/
+ (instancetype)CreateTcpIPStream:(id)delegate
{
return [[TCPIPStreamalloc] initTcpIPSteam:delegate];
}
/**初始化*/
- (instancetype)initTcpIPSteam:(id)delegate
{
if(self= [super init]) {
_m_pSocket= [[AsyncSocketalloc]initWithDelegate:self];
_delegate= delegate;
m_nBufferLen=0;
}
return self;
}
二,建立连接
1,每次重新连接服务器时都要将缓冲区相关变量设置成初始值,将buffer设置成0;
2,连接服务器前一定要判断该socket断开,否则会报错;
3,网路检测,是检查设备网络情况;
4,调用- (BOOL)connectToHost:(NSString*)hostname onPort:(UInt16)port error:(NSError**)errPtr 与服务器建立连接
根据errPtr的错误信息做处理;
5,这个是避免锁屏的时候socket断开(不处理会抛异常)
-(void)CreateConnectWithAddress:(NSString*)address port:(uint)port
{
//清零数据
m_nBufferLen=0;
memset(m_pBuffer,0,sizeof(uint8_t)*SOCKET_TCP_BUFFER); //1
//重置网络
[self.m_pSocket disconnect]; //2
//网络检测 //3
//连接网络这里要处理是否链接成功
NSError*erro;
if(self.m_pSocket==nil) {
self.m_pSocket= [[AsyncSocketalloc]initWithDelegate:self];
}
BOOLisSuccess = [self.m_pSocket connectToHost:addresson Port:porterror:&erro]; //4
NSLog(@"%@",@(isSuccess));
NSAssert(isSuccess,@"连接失败");
//设置锁屏连接不断 //5
CFReadStreamSetProperty([self.m_pSocketgetCFReadStream],kCFStreamNetworkServiceType,kCFStreamNetworkServiceTypeVoIP);
CFWriteStreamSetProperty([self.m_pSocketgetCFWriteStream],kCFStreamNetworkServiceType,kCFStreamNetworkServiceTypeVoIP);
}
三,发送数据
为了安全,可以在发送前进行加密
-(bool)SendToServer:(uint8_t*)pData size:(uint)nDataSize
{
//这里处理加密
//发送数据
[self.m_pSocket writeData:[NSDatadataWithBytes:pData length:nDataSize]withTimeout:-1tag:0];
returnYES;
}
四,接收数据
接收数据接口的实现是根据客户端与服务端自定义协议实现的,后面我回专门用一篇文章来讲这部分的实现。-(void) onSocket:(AsyncSocket*)sock didReadData:(NSData*)data withTag:(long)tag
五,关闭
-(void)ClosedStream
{
[self.m_pSocket disconnect];
}
六,协议实现
与服务器连接成功后,会回调这个函数,在此函数调用读取数据的api,当有数据来时就会回调-(void) onSocket:(AsyncSocket*)sock didReadData:(NSData*)data withTag:(long)tag。
/**建立连接后调用*/
- (void)onSocket:(AsyncSocket*)sock didConnectToHost:(NSString*)host port:(UInt16)port
{
[self.m_pSocket readDataWithTimeout:-1tag:0];
}
这个socket关闭(正常或异常)时会调用,这里是处理断线重连的地方,在网络开发中,网络的切换,前后台切换都会导致连接断开,很好的处理这些情况会很大程度上提高用户体验,后面会具体讲处理的思路。
-(void) onSocket:(AsyncSocket*)socket willDisconnectWithError:(NSError*)err