socket使用注意事项
1. timeout < 0时,表示没有超时;如果设置超时时间,并且socket超时之后,
socket会断掉,需要重连
2. 用AsyncSocket连接服务器时,不管服务器有没有开,[client connectToHost:hostIP onPort:hostPort error:&err]
这一句一直返回YES,所以判断服务器有没有连接成功
3. 当读的时候,需要判断长度是否足够,如果不够需要再次设置[socket readDataWithTimeout:-1 tag:0];
4.socket的3种连接状态:
连接中:
已连接:
连接断开:
5.如何判断socket当前处于那种状态
把asyncsocket.m文件中,
- (
BOOL
)isDisconnected;方法放到asyncsocket.h文件中,该方法可判断当前socket是否处于连接断开状态;
- (BOOL)isConnected;可用来判断socket是否处于连接成功状态;
如果socket即不处于已连接和连接断开的状态,那么socket此时处于连接中的状态.处于连接中的socket不能再次发起连接,此时会报错
6.如何判断socket是用户主动断开还是服务器断开
当你需要主要断开连接时可以通过:
setUserData:(long)userData;
给socket.userData字段设一个值,在- (void)onSocketDidDisconnect:(AsyncSocket *)sock 方法中,根据socket.userData的值判断是用户主动断开还是服务器断开
7.一般一个应用生成一个socket实例来建立连接,不断新开实例会增加服务器压力
8.关于socket粘包问题
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
//把数据放到缓冲区
[self.bufferData appendData:data];
//获取包的总长度,PackageHeadBytesCount包中表示包大小的字节数
NSData *headData = [self.bufferData subdataWithRange:NSMakeRange(0, PackageHeadBytesCount)];
//获取包的大小
short totalLen = [DataManager packageTotalLengthWithData:headData];
if (self.bufferData.length < totalLen){
NSLog(@"*** 包体长度 < 要的长度");
}else if (self.bufferData.length > totalLen){
//此种情况下发生了粘包,下面是处理粘包的步骤
NSLog(@"*** 包体长度 > 要的长度");
short newTotalLen = totalLen;
while (self.bufferData.length >= newTotalLen) {
NSUInteger leftLen = self.bufferData.length - newTotalLen;
//从缓冲区取一包数据
NSData *packageData = [self.bufferData subdataWithRange:NSMakeRange(0, newTotalLen)];
NSData *leftData;
if (leftLen == 0){
leftData = [NSMutableData data];
}else {
leftData = [self.bufferData subdataWithRange:NSMakeRange(newTotalLen, leftLen)];
}
//缓冲区数据设置为减掉一包数据后的数据
[self.bufferData setData:leftData];
//处理拿到的一包数据
[self handleRcvPackageData:packageData];
if (leftLen == 0){
break;
}
newTotalLen = [DataManager packageTotalLengthWithData:[NSData dataWithData:self.bufferData]];
}
}else {
NSLog(@"*** 包体长度 == 要的长度");
NSData *packageData = [NSData dataWithData:self.bufferData];
//清空缓冲区
self.bufferData = [NSMutableData data];
//处理拿到的一个包的数据
[self handleRcvPackageData:packageData];
}
[self.socket readDataWithTimeout:-1 tag:0];
}
9.如何保持socket的长连接状态
通过发心跳来保持,心跳时间间隔可以和服务器来商定
10.socket不用时要进行如下操作:
[self.socket setDelegate:nil];
[self.socket disconnect];
self.socket = nil;
11.timeout字段设为-1时,socket为一直等待的read或write
12.socket每次重连的时候要把缓冲区的数据清空(sessioninfo获取不到的原因)