iOS GCDAsyncSocket源码分析(二)

1,894 阅读25分钟

由于上一篇文章篇幅过长移到这边。

3.read&write
  • 先看write
//写数据对外方法
- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
{
	if ([data length] == 0) return;
	
    //初始化写包,可知write操作是用GCDAsyncWritePacket这种包的形式发送的,如果没错的话,read应该也是这样吧。
	GCDAsyncWritePacket *packet = [[GCDAsyncWritePacket alloc] initWithData:data timeout:timeout tag:tag];
	//异步
	dispatch_async(socketQueue, ^{ @autoreleasepool {
		
		LogTrace();
		
		if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites))
		{
            //writeQueue是一个数组,把当前packet添加进去
			[writeQueue addObject:packet];
            //还没看到write(),得继续跳转
			[self maybeDequeueWrite];
		}
	}});
	
	// Do not rely on the block being run in order to release the packet,
	// as the queue might get released without the block completing.
}

这个方法只是构建了一个GCDAsyncWritePacket包,添加到writequeue数组中,然后继续调用别的方法

- (void)maybeDequeueWrite
{
	LogTrace();
	NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
	
	
	// If we're not currently processing a write AND we have an available write stream
    //currentWrite也是一个GCDAsyncWritePacket包
    //如果currentWrite为空,且socket已经连接
	if ((currentWrite == nil) && (flags & kConnected))
	{
        //如果用来写的数组数量大于0
		if ([writeQueue count] > 0)
		{
			// Dequeue the next object in the write queue
            //将第一个包赋值给currentWrite,并从数组中移除
			currentWrite = [writeQueue objectAtIndex:0];
			[writeQueue removeObjectAtIndex:0];
			
			//TLS,如果是GCDAsyncSpecialPacket,一般不走这里
			if ([currentWrite isKindOfClass:[GCDAsyncSpecialPacket class]])
			{
				LogVerbose(@"Dequeued GCDAsyncSpecialPacket");
				
				// Attempt to start TLS
				flags |= kStartingWriteTLS;
				
				// This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set
				[self maybeStartTLS];
			}
			else
			{
				LogVerbose(@"Dequeued GCDAsyncWritePacket");
				
				// Setup write timer (if needed)
                //设置一个GCD timer 来记录超时时间
				[self setupWriteTimerWithTimeout:currentWrite->timeout];
				
				// 开始write
				[self doWriteData];
			}
		}
        // flags & kDisconnectAfterWrites 跟 数组小于等于0 的 意思差不多
		else if (flags & kDisconnectAfterWrites)
		{
            //如果没有可读任务,直接关闭socket
			if (flags & kDisconnectAfterReads)
			{
				if (([readQueue count] == 0) && (currentRead == nil))
				{
					[self closeWithError:nil];
				}
			}
			else
			{
				[self closeWithError:nil];
			}
		}
	}
}

这个方法主要的就是给currentWrite赋值,writeQueue的数量判断,大于0就继续往下,小于等于0就断开连接。还做了一步[GCDAsyncSpecialPacket class]的判断,我们write的时候,进来的是普通包,不是special包,基本上不会走进去,所以我那继续往下走就是执行[self doWriteData];这又是一个很长的方法。这里面包含了很多flags判断操作,比如:socket安全等等,需要有设置才会执行

- (void)doWriteData
{
	LogTrace();
    //currentWrite为空,不写
	if ((currentWrite == nil) || (flags & kWritesPaused))
	{
		LogVerbose(@"No currentWrite or kWritesPaused");
    
		if ([self usingCFStreamForTLS])
		{
			//啥也不干
		}
		else
		{
            //如果socket中可接受写数据,防止反复触发写source,挂起
			if (flags & kSocketCanAcceptBytes)
			{
				[self suspendWriteSource];
			}
		}
		return;
	}
	
    //如果当前socket无法在写数据了
	if (!(flags & kSocketCanAcceptBytes))
	{
		LogVerbose(@"No space available to write...");
		
		// No space available to write.
		
        //如果不是cfstream
		if (![self usingCFStreamForTLS])
		{
			// Need to wait for writeSource to fire and notify us of
			// available space in the socket's internal write buffer.
            //则恢复写source,当有空间去写的时候,会触发回来
			[self resumeWriteSource];
		}
		return;
	}
	
    //如果正在进行TLS认证,就是那个specialpacket,我们当前不是这个所以先跳过
	if (flags & kStartingWriteTLS)
	{
		LogVerbose(@"Waiting for SSL/TLS handshake to complete");
		
		// The writeQueue is waiting for SSL/TLS handshake to complete.
		
		if (flags & kStartingReadTLS)
		{
            //如果是安全通道,并且I/O阻塞,那么重新去握手
			if ([self usingSecureTransportForTLS] && lastSSLHandshakeError == errSSLWouldBlock)
			{
				// We are in the process of a SSL Handshake.
				// We were waiting for available space in the socket's internal OS buffer to continue writing.
			
				[self ssl_continueSSLHandshake];
			}
		}
        //说明不走`TLS`了,因为只支持写的TLS
		else
		{
			// We are still waiting for the readQueue to drain and start the SSL/TLS process.
			// We now know we can write to the socket.
			
            //挂起写source
			if (![self usingCFStreamForTLS])
			{
				// Suspend the write source or else it will continue to fire nonstop.
				[self suspendWriteSource];
			}
		}
		
		return;
	}
	
	// Note: This method is not called if currentWrite is a GCDAsyncSpecialPacket (startTLS packet)
	
    //开始写数据
    
	BOOL waiting = NO;
	NSError *error = nil;
	size_t bytesWritten = 0;
	
    //安全连接
	if (flags & kSocketSecure)
	{
           //这里先省略,关键看普通连接。有需要仔细了解的可以私信我。我给你发代码- -
           ...
	} 
    //普通socket
	else
	{
        //拿到当前socket
		int socketFD = (socket4FD != SOCKET_NULL) ? socket4FD : (socket6FD != SOCKET_NULL) ? socket6FD : socketUN;
        //得到指针偏移
		const uint8_t *buffer = (const uint8_t *)[currentWrite->buffer bytes] + currentWrite->bytesDone;
        // 要写的数据大小
		NSUInteger bytesToWrite = [currentWrite->buffer length] - currentWrite->bytesDone;
		
		if (bytesToWrite > SIZE_MAX) // NSUInteger may be bigger than size_t (write param 3)
		{
			bytesToWrite = SIZE_MAX;
		}
		//直接写,熟悉的write()
		ssize_t result = write(socketFD, buffer, (size_t)bytesToWrite);
		LogVerbose(@"wrote to socket = %zd", result);
		
		// 结果判断
		if (result < 0)
		{
            //IO阻塞
			if (errno == EWOULDBLOCK)
			{
				waiting = YES;
			}
			else
			{
				error = [self errnoErrorWithReason:@"Error in write() function"];
			}
		}
		else
		{
            //得到写的大小
			bytesWritten = result;
		}
	}
	
	//注意,如果用CFStream,很可能会被恶意的放置数据 阻塞socket
    
    //如果等待,则恢复写source
	if (waiting)
	{
        //把socket可接受数据的标记去掉
		flags &= ~kSocketCanAcceptBytes;
		
		if (![self usingCFStreamForTLS])
		{
            //恢复写source
			[self resumeWriteSource];
		}
	}
	
	// Check our results
	
    //判断是否完成
	BOOL done = NO;
	//判断已写大小
	if (bytesWritten > 0)
	{
		// Update total amount read for the current write
        //更新当前总共写的大小
		currentWrite->bytesDone += bytesWritten;
		LogVerbose(@"currentWrite->bytesDone = %lu", (unsigned long)currentWrite->bytesDone);
		
		// Is packet done?
        //判断当前写包是否写完
		done = (currentWrite->bytesDone == [currentWrite->buffer length]);
	}
	
    //如果完成了
	if (done)
	{
        //完成操作,回调发送成功代理事件,注意,代理回调是这里
		[self completeCurrentWrite];
		
		if (!error)
		{
			dispatch_async(socketQueue, ^{ @autoreleasepool{
				//开始下一次的读取任务
				[self maybeDequeueWrite];
			}});
		}
	}
    //未完成
	else
	{
		//如果不是等待 而且没有出错
		if (!waiting && !error)
		{
            //这是我们写了一部分数据的情况。
            
			//去掉可接受数据的标记
			flags &= ~kSocketCanAcceptBytes;
			//再去等读source触发
			if (![self usingCFStreamForTLS])
			{
				[self resumeWriteSource];
			}
		}
		
        //如果已写大于0
		if (bytesWritten > 0)
		{
			__strong id theDelegate = delegate;

            //调用写的进度代理
			if (delegateQueue && [theDelegate respondsToSelector:@selector(socket:didWritePartialDataOfLength:tag:)])
			{
				long theWriteTag = currentWrite->tag;
				
				dispatch_async(delegateQueue, ^{ @autoreleasepool {
					
					[theDelegate socket:self didWritePartialDataOfLength:bytesWritten tag:theWriteTag];
				}});
			}
		}
	}
	
	// Check for errors
	//如果有错,则报错断开连接
	if (error)
	{
		[self closeWithError:[self errnoErrorWithReason:@"Error in write() function"]];
	}
}

这个方法贼长,长的主要原因还是TSL,SSL这两个安全传输协议的处理,我们这里就先看看普通的吧...那些实在很长,注释也很多。 接下来看read,看看会发现,方法格式差不多

  • read
- (void)readDataWithTimeout:(NSTimeInterval)timeout
                     buffer:(NSMutableData *)buffer
               bufferOffset:(NSUInteger)offset
                  maxLength:(NSUInteger)length
                        tag:(long)tag
{
	if (offset > [buffer length]) {
		LogWarn(@"Cannot read: offset > [buffer length]");
		return;
	}
	
	GCDAsyncReadPacket *packet = [[GCDAsyncReadPacket alloc] initWithData:buffer
	                                                          startOffset:offset
	                                                            maxLength:length
	                                                              timeout:timeout
	                                                           readLength:0
	                                                           terminator:nil
	                                                                  tag:tag];
	
	dispatch_async(socketQueue, ^{ @autoreleasepool {
		
		LogTrace();
		
		if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites))
		{
            //往读的队列添加任务,任务是包的形式
			[readQueue addObject:packet];
			[self maybeDequeueRead];
		}
	}});
}

同样是构造一个GCDAsyncReadPacket包,然后添加到数组中,然后执行下一个方法

- (void)maybeDequeueRead
{
	LogTrace();
	NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
    
    //如果当前读的包为空,而且flag为已连接
	if ((currentRead == nil) && (flags & kConnected))
	{
        //如果读的queue大于0 (里面装的是我们封装的GCDAsyncReadPacket数据包)
		if ([readQueue count] > 0)
		{
			// Dequeue the next object in the write queue
            //使得下一个对象从写的queue中离开
            
            //从readQueue中拿到第一个写的数据
			currentRead = [readQueue objectAtIndex:0];
            //移除
			[readQueue removeObjectAtIndex:0];
			
            //我们的数据包,如果是GCDAsyncSpecialPacket这种类型,这个包里装了TLS的一些设置
            //如果是这种类型的数据,那么我们就进行TLS
			if ([currentRead isKindOfClass:[GCDAsyncSpecialPacket class]])
			{
				LogVerbose(@"Dequeued GCDAsyncSpecialPacket");
				
				// Attempt to start TLS
                //标记flag为正在读取TLS
				flags |= kStartingReadTLS;
				
				// This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set
                //只有读写都开启了TLS,才会做TLS认证
				[self maybeStartTLS];
			}
			else
			{
				LogVerbose(@"Dequeued GCDAsyncReadPacket");
				
				// Setup read timer (if needed)
                //设置读的任务超时,每次延时的时候还会调用 [self doReadData];
				[self setupReadTimerWithTimeout:currentRead->timeout];
				
				// Immediately read, if possible
                //读取数据
				[self doReadData];
			}
		}
        
        //读的队列没有数据,标记flag为,读了没有数据则断开连接状态
		else if (flags & kDisconnectAfterReads)
		{
            //如果标记有写然后断开连接
			if (flags & kDisconnectAfterWrites)
			{
                //如果写的队列为0,而且写为空
				if (([writeQueue count] == 0) && (currentWrite == nil))
				{
                    //断开连接
					[self closeWithError:nil];
				}
			}
			else
			{
                //断开连接
				[self closeWithError:nil];
			}
		}
        //如果有安全socket。
		else if (flags & kSocketSecure)
		{
			[self flushSSLBuffers];	
            //如果可读字节数为0
			if ([preBuffer availableBytes] == 0)
			{
                //CFStream形式TLS
				if ([self usingCFStreamForTLS]) {
					// Callbacks never disabled
				}
				else {
                    //重新恢复读的source。因为每次开始读数据的时候,都会挂起读的source
					[self resumeReadSource];
				}
			}
		}
	}
}

也是一系列的安全协议判断并最终走向[self doReadData];这个方法比write还长,我觉得有必要列一下这个方法里面都做了什么。。。

1.判断currentRead是否为空,为空就挂起readSource 2.判断TLS 3.从preBuffer区读取数据 4.从socket中读取数据 5.读取完代理回调 6.错误检查

- (void)doReadData
{
	LogTrace();
	
    //如果当前读取的包为空,或者flag为读取停止,这两种情况是不能去读取数据的
	if ((currentRead == nil) || (flags & kReadsPaused))
	{
		LogVerbose(@"No currentRead or kReadsPaused");
		
		// Unable to read at this time
		//如果是安全的通信,通过TLS/SSL
		if (flags & kSocketSecure)
		{
			// Here's the situation:
			// 这有一个场景
			// We have an established secure connection.
            //我们有一个确定的安全的连接
			// There may not be a currentRead, but there might be encrypted data sitting around for us.
            //可能没有立即去读,但是或许已经有加密的数据闲置在那
			// When the user does get around to issuing a read, that encrypted data will need to be decrypted.
			// 当用户开始进行一个read,这些加密的数据需要被解码
			// So why make the user wait?
            //所以为什么让用户等待?
			// We might as well get a head start on decrypting some data now.
			// 我们最好可以先进行数据解密
			// The other reason we do this has to do with detecting a socket disconnection.
            //另外的理由是,我们做这些不得不去检测socket的断开连接
			// The SSL/TLS protocol has it's own disconnection handshake.
            //SSL/TLS协议有自己的断开连接的握手
			// So when a secure socket is closed, a "goodbye" packet comes across the wire.
            //所以当一个安全连接关闭,一个“goodbye"数据包会被发送在电报中
			// We want to make sure we read the "goodbye" packet so we can properly detect the TCP disconnection.
            //我们想要确保读到“goodbye”数据包,因此我们可以确定检测到TCP连接断开
			
            //刷新SSLBuffer,把数据从链路上移到prebuffer中 (当前暂停的时候做)
			[self flushSSLBuffers];
		}
		
        //判断是否用的是 CFStream的TLS
		if ([self usingCFStreamForTLS])
		{
			// CFReadStream only fires once when there is available data.
			// It won't fire again until we've invoked CFReadStreamRead.
            //CFReadStream只会调起一次,当有可读的数据。 不会再次被调用,直到我们唤醒CFReadStreamRead。
            // source --> data --> stream
		}
		else
		{
			// If the readSource is firing, we need to pause it
			// or else it will continue to fire over and over again.
			// 
			// If the readSource is not firing,
			// we want it to continue monitoring the socket.
			//如果读的source正在触发,我们需要去停止它,否则它会持续的被触发一遍又一遍。(要等我们把现有传过来的数据读完,才能触发下一次。)
            //如果读的source没有触发。我们想要它继续去监视socket.
            //挂起source
			if (socketFDBytesAvailable > 0)
			{
				[self suspendReadSource];
			}
		}
		return;
	}
	
    //当前数据包不为空或者flag不为kReadsPaused,正式开始读取数据
    //声明是否可读,可读数据为多大
	BOOL hasBytesAvailable = NO;
	unsigned long estimatedBytesAvailable = 0;
	
    //如果用了CFStream
	if ([self usingCFStreamForTLS])
	{
		#if TARGET_OS_IPHONE
		
		// Requested CFStream, rather than SecureTransport, for TLS (via GCDAsyncSocketUseCFStreamForTLS)
		
        //不需要得到数据大小
		estimatedBytesAvailable = 0;
        //判断如果状态可读而且有可读数据,hasBytesAvailable则为YES
		if ((flags & kSecureSocketHasBytesAvailable) && CFReadStreamHasBytesAvailable(readStream))
			hasBytesAvailable = YES;
		else
			hasBytesAvailable = NO;
		
		#endif
	}
	else
	{
        //拿到当前读到的数据大小,安全通道的和普通socket数据都和 socketFDBytesAvailable 有关
		estimatedBytesAvailable = socketFDBytesAvailable;
		//如果是安全socket
		if (flags & kSocketSecure)
		{
            // There are 2 buffers to be aware of here.
            // 这里有2个buffer需要知道,一个是sslPreBuffer还有一个是安全传输中未读取的buffer
			// We are using SecureTransport, a TLS/SSL security layer which sits atop TCP.
            //我们使用了安全的传输,一个TLS/SSL在TCP上
			// We issue a read to the SecureTranport API, which in turn issues a read to our SSLReadFunction.
            //我们发出read在安全传输的API上,其实就是发出read在SSLReadFunction上
			// Our SSLReadFunction then reads from the BSD socket and returns the encrypted data to SecureTransport.
            //我们SSLReadFunction 从BSD socket去读,并且返回加密的数据到安全传输中。
			// SecureTransport then decrypts the data, and finally returns the decrypted data back to us.
			// 然后安全传输返回解密的数据,最终把解密的数据返回给我们
			// The first buffer is one we create.
            //第一个buffe是我们创建的
			// SecureTransport often requests small amounts of data.
            //安全的传输经常需要少量的数据
			// This has to do with the encypted packets that are coming across the TCP stream.
            //他们不得不用加密包来穿过TCP流
			// But it's non-optimal to do a bunch of small reads from the BSD socket.
            //但是,这是不是最佳的,从BSD Socket上,进行一堆小的阅读
			// So our SSLReadFunction reads all available data from the socket (optimizing the sys call)
            //所以我们SSLReadFunction从socket中读取所有提供的数据(最佳的方式)
			// and may store excess in the sslPreBuffer.
            //可能在sslPreBuffer中存储超出的部分
			
            //预估的读取大小再加上 ssl中可读的
			estimatedBytesAvailable += [sslPreBuffer availableBytes];
			
			// The second buffer is within SecureTransport.
            //第二个Buffer在安全传输中
			// As mentioned earlier, there are encrypted packets coming across the TCP stream.
            //像之前提到的,这里有加密的包在TCP流中
			// SecureTransport needs the entire packet to decrypt it.
            //安全传输需要把整个包解密
			// But if the entire packet produces X bytes of decrypted data,
            //但是如果整个包只有 X字节是加密的数据
			// and we only asked SecureTransport for X/2 bytes of data,
            //而我们仅仅访问了 SecureTransport中一半字节的数据
			// it must store the extra X/2 bytes of decrypted data for the next read.
			// 我们必须存储另一半在下一次读取中
			// The SSLGetBufferedReadSize function will tell us the size of this internal buffer.
            //SSLGetBufferedReadSize方法,将告诉我们内部的buffer大小
			// From the documentation:
			// 
			// "This function does not block or cause any low-level read operations to occur."
			//从文档中:这个方法不会阻塞和引起低级别的读取操作发生
            
			size_t sslInternalBufSize = 0;
            //拿到SSL上下文中的大小,也就是计算我们能从SSLReead中能获取到的数据大小
			SSLGetBufferedReadSize(sslContext, &sslInternalBufSize);
			//加到预估大小中
			estimatedBytesAvailable += sslInternalBufSize;
		}
		//如果 estimatedBytesAvailable 大于0 为YES
		hasBytesAvailable = (estimatedBytesAvailable > 0);
	}
	
    //如果没有数据可读  --  一次传完的包
	if ((hasBytesAvailable == NO) && ([preBuffer availableBytes] == 0))
	{
		LogVerbose(@"No data available to read...");
		
		//而且不是用CFStream
		if (![self usingCFStreamForTLS])
		{
			// Need to wait for readSource to fire and notify us of
			// available data in the socket's internal read buffer.
			//恢复读的source
			[self resumeReadSource];
		}
		return;
	}
	//如果开始 kStartingReadTLS,说明正在准备握手,那么我们不能进行读取操作,要直接返回
	if (flags & kStartingReadTLS)
	{
		LogVerbose(@"Waiting for SSL/TLS handshake to complete");
		
		// The readQueue is waiting for SSL/TLS handshake to complete.
		//如果正在写的TLS,如果上一次是阻塞错误,那么在重新去握手,(防止一次握手阻塞而失败导致不再握手)
		if (flags & kStartingWriteTLS)
		{
            //如果用的是非CFStreamTLS,即安全的TLS  而且上一次握手错误为 IO阻塞的
			if ([self usingSecureTransportForTLS] && lastSSLHandshakeError == errSSLWouldBlock)
			{
				// We are in the process of a SSL Handshake.
				// We were waiting for incoming data which has just arrived.
                //SSL的握手
				[self ssl_continueSSLHandshake];
			}
		}
		else
		{
			// We are still waiting for the writeQueue to drain and start the SSL/TLS process.
			// We now know data is available to read.
			
            //如果当前不是CFStream的方式
			if (![self usingCFStreamForTLS])
			{
				// Suspend the read source or else it will continue to fire nonstop.
                //挂起读的queue
				[self suspendReadSource];
			}
		}
		
		return;
	}
	
    //是否完成读的操作
	BOOL done        = NO;  // Completed read operation
    //错误
	NSError *error   = nil; // Error occurred
	
    //当前总读的数据量
	NSUInteger totalBytesReadForCurrentRead = 0;
	
	// 
	// STEP 1 - READ FROM PREBUFFER
	// 
	//先从提前缓冲区去读,如果缓冲区可读大小大于0
	if ([preBuffer availableBytes] > 0)
	{
		// There are 3 types of read packets:
        //
        // 1) Read all available data.
		// 2) Read a specific length of data.
		// 3) Read up to a particular terminator.
		//3种类型的读法,1、全读、2、读取特定长度、3、读取到一个明确的界限
        
		NSUInteger bytesToCopy;
		
        //如果当前读的数据界限不为空
		if (currentRead->term != nil)
		{
			// Read type #3 - read up to a terminator
			//直接读到界限
			bytesToCopy = [currentRead readLengthForTermWithPreBuffer:preBuffer found:&done];
		}
		else
		{
			// Read type #1 or #2
			//读取数据,读到指定长度或者数据包的长度为止
			bytesToCopy = [currentRead readLengthForNonTermWithHint:[preBuffer availableBytes]];
		}
		
		// Make sure we have enough room in the buffer for our read.
		//从上两步拿到我们需要读的长度,去看看有没有空间去存储
		[currentRead ensureCapacityForAdditionalDataOfLength:bytesToCopy];
		
		// Copy bytes from prebuffer into packet buffer

        //拿到我们需要追加数据的指针位置
        //当前读的数据 + 开始偏移 + 已经读完的??
		uint8_t *buffer = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset +
		                                                                  currentRead->bytesDone;
		//从prebuffer处复制过来数据,bytesToCopy长度
		memcpy(buffer, [preBuffer readBuffer], bytesToCopy);
		
		// Remove the copied bytes from the preBuffer
        //从preBuffer移除掉已经复制的数据
		[preBuffer didRead:bytesToCopy];
		
        
		LogVerbose(@"copied(%lu) preBufferLength(%zu)", (unsigned long)bytesToCopy, [preBuffer availableBytes]);
		
		// Update totals
		
        //已读的数据加上
		currentRead->bytesDone += bytesToCopy;
        //当前已读的数据加上
		totalBytesReadForCurrentRead += bytesToCopy;
		
		// Check to see if the read operation is done
		//判断是不是读完了
		if (currentRead->readLength > 0)
		{
			// Read type #2 - read a specific length of data
			//如果已读 == 需要读的长度,说明已经读完
			done = (currentRead->bytesDone == currentRead->readLength);
		}
        //判断界限标记
		else if (currentRead->term != nil)
		{
			// Read type #3 - read up to a terminator
			
			// Our 'done' variable was updated via the readLengthForTermWithPreBuffer:found: method
			//如果没做完,且读的最大长度大于0,去判断是否溢出
			if (!done && currentRead->maxLength > 0)
			{
				// We're not done and there's a set maxLength.
				// Have we reached that maxLength yet?
				
                //如果已读的大小大于最大的大小,则报溢出错误
				if (currentRead->bytesDone >= currentRead->maxLength)
				{
					error = [self readMaxedOutError];
				}
			}
		}
		else
		{
			// Read type #1 - read all available data
			// 
			// We're done as soon as
			// - we've read all available data (in prebuffer and socket)
			// - we've read the maxLength of read packet.
			//判断已读大小和最大大小是否相同,相同则读完
			done = ((currentRead->maxLength > 0) && (currentRead->bytesDone == currentRead->maxLength));
		}
		
	}
	
	// 
	// STEP 2 - READ FROM SOCKET
	// 从socket中去读取
	
    //是否读到EOFException ,这个错误指的是文件结尾了还在继续读,就会导致这个错误被抛出
	BOOL socketEOF = (flags & kSocketHasReadEOF) ? YES : NO;  // Nothing more to read via socket (end of file)
    
    //如果没完成,且没错,没读到结尾,且没有可读数据了
	BOOL waiting   = !done && !error && !socketEOF && !hasBytesAvailable; // Ran out of data, waiting for more
    
    //如果没完成,且没错,没读到结尾,有可读数据
	if (!done && !error && !socketEOF && hasBytesAvailable)
	{
        //断言,有可读数据
		NSAssert(([preBuffer availableBytes] == 0), @"Invalid logic");
        //是否读到preBuffer中去
        BOOL readIntoPreBuffer = NO;
		uint8_t *buffer = NULL;
		size_t bytesRead = 0;
		
        //如果flag标记为安全socket
		if (flags & kSocketSecure)
		{
            //如果使用CFStream
			if ([self usingCFStreamForTLS])
			{
				#if TARGET_OS_IPHONE
				
				// Using CFStream, rather than SecureTransport, for TLS
				//默认读的大小32KB
				NSUInteger defaultReadLength = (1024 * 32);
				
                //决定我们读的字节大小,和是否使用prebuffer
				NSUInteger bytesToRead = [currentRead optimalReadLengthWithDefault:defaultReadLength
				                                                   shouldPreBuffer:&readIntoPreBuffer];
				
				// Make sure we have enough room in the buffer for our read.
				//
				// We are either reading directly into the currentRead->buffer,
				// or we're reading into the temporary preBuffer.
				//如果使用preBuffer,则去确保有这么大的空间来存
				if (readIntoPreBuffer)
				{
					[preBuffer ensureCapacityForWrite:bytesToRead];
					//拿到写的buffer
					buffer = [preBuffer writeBuffer];
				}
                //不用prebuffer
				else
				{
                    //确保大小,其实不用。。
					[currentRead ensureCapacityForAdditionalDataOfLength:bytesToRead];
					
                    //获取到当前buffer上次写到的偏移位置
					buffer = (uint8_t *)[currentRead->buffer mutableBytes]
					       + currentRead->startOffset
					       + currentRead->bytesDone;
				}
				
				// Read data into buffer
                
#pragma mark - 开始读取数据 CFStream
				//从readStream中读取数据,到buffer中
				CFIndex result = CFReadStreamRead(readStream, buffer, (CFIndex)bytesToRead);
				LogVerbose(@"CFReadStreamRead(): result = %i", (int)result);
				
                //读取失败
				if (result < 0)
				{
					error = (__bridge_transfer NSError *)CFReadStreamCopyError(readStream);
				}
                // 读取抛出了EOFException,到数据边界了
				else if (result == 0)
				{
					socketEOF = YES;
				}
                //正常读取
				else
				{
					waiting = YES;
					bytesRead = (size_t)result;
				}
				
				// We only know how many decrypted bytes were read.
				// The actual number of bytes read was likely more due to the overhead of the encryption.
				// So we reset our flag, and rely on the next callback to alert us of more data.
                
                //移除仍然有数据可读的标记
				flags &= ~kSecureSocketHasBytesAvailable;
				
				#endif
			}
			else
			{
                //用安全传输来
				// Using SecureTransport for TLS
				//
				// We know:
				// - how many bytes are available on the socket
				// - how many encrypted bytes are sitting in the sslPreBuffer
				// - how many decypted bytes are sitting in the sslContext
				//
				// But we do NOT know:
				// - how many encypted bytes are sitting in the sslContext
				//
				// So we play the regular game of using an upper bound instead.
				
                //也是默认32KB
				NSUInteger defaultReadLength = (1024 * 32);
				
                //如果默认大小小于预估的大小,则让默认大小的 =  预估大小 + 16KB ,16KB干嘛用的??
				if (defaultReadLength < estimatedBytesAvailable) {
					defaultReadLength = estimatedBytesAvailable + (1024 * 16);
				}
				//去要读的大小,还有是否走Prebuffer
				NSUInteger bytesToRead = [currentRead optimalReadLengthWithDefault:defaultReadLength
				                                                   shouldPreBuffer:&readIntoPreBuffer];
				
                //如果要读的大小大于最大值 ,则让其等于最大值
				if (bytesToRead > SIZE_MAX) { // NSUInteger may be bigger than size_t
					bytesToRead = SIZE_MAX;
				}
				
				// Make sure we have enough room in the buffer for our read.
				//
				// We are either reading directly into the currentRead->buffer,
				// or we're reading into the temporary preBuffer.
				
                //还是去确保最大空间,并且拿到写的头指针
				if (readIntoPreBuffer)
				{
					[preBuffer ensureCapacityForWrite:bytesToRead];
					
					buffer = [preBuffer writeBuffer];
				}
				else
				{
					[currentRead ensureCapacityForAdditionalDataOfLength:bytesToRead];
					
					buffer = (uint8_t *)[currentRead->buffer mutableBytes]
					       + currentRead->startOffset
					       + currentRead->bytesDone;
				}
				
				// The documentation from Apple states:
				// 
				//     "a read operation might return errSSLWouldBlock,
				//      indicating that less data than requested was actually transferred"
				// 
				// However, starting around 10.7, the function will sometimes return noErr,
				// even if it didn't read as much data as requested. So we need to watch out for that.
				
				OSStatus result;
            
#pragma mark - 开始读取数据 SSLRead
                //循环去读
				do
				{
                    //拿到当前写到的buffer位置
                    //头指针 + 读了的大小
					void *loop_buffer = buffer + bytesRead;
                    
                    //得到还需要读的大小
					size_t loop_bytesToRead = (size_t)bytesToRead - bytesRead;
                    //设置这一次循环读的进度
					size_t loop_bytesRead = 0;
                    
					//用ssl方式去读取数据,头指针为loop_buffer,大小为loop_bytesToRead,进度为loop_bytesRead
					result = SSLRead(sslContext, loop_buffer, loop_bytesToRead, &loop_bytesRead);
					LogVerbose(@"read from secure socket = %u", (unsigned)loop_bytesRead);
					
                    //读了的大小加进度
					bytesRead += loop_bytesRead;
					
				}
                //如果没出错,且读的大小小于需要读的大小,就一直循环
                while ((result == noErr) && (bytesRead < bytesToRead));
				
				//如果出错
				if (result != noErr)
				{
                    //如果是IO阻塞的错误, waiting
					if (result == errSSLWouldBlock)
						waiting = YES;
					else
					{
                        //如果是SSL连接断开的错误
						if (result == errSSLClosedGraceful || result == errSSLClosedAbort)
						{
							// We've reached the end of the stream.
							// Handle this the same way we would an EOF from the socket.
                            //说明到边界了
							socketEOF = YES;
                            //把错误赋值给SSLErrCode
							sslErrCode = result;
						}
						else
						{
                            //直接拿到SSL数据错误
							error = [self sslError:result];
						}
					}
					// It's possible that bytesRead > 0, even if the result was errSSLWouldBlock.
                    //很有可能bytesRead中有数据,即使结果是IO阻塞的错误
					// This happens when the SSLRead function is able to read some data,
					// but not the entire amount we requested.
					
                    
					if (bytesRead <= 0)
					{
						bytesRead = 0;
					}
				}
				//不要修改 socketFDBytesAvailable 可读数据大小,因为这个会在 SSLReadFunction中被修改
				// Do not modify socketFDBytesAvailable.
				// It will be updated via the SSLReadFunction().
			}
		}
		else
		{
			// Normal socket operation
			//普通的socket 操作
            
			NSUInteger bytesToRead;
			
			// There are 3 types of read packets:
			//
			// 1) Read all available data.
			// 2) Read a specific length of data.
			// 3) Read up to a particular terminator.
			
            //和上面类似,读取到边界标记??不是吧
			if (currentRead->term != nil)
			{
				// Read type #3 - read up to a terminator
				
                //读这个长度,如果到maxlength,就用maxlength。看如果可用空间大于需要读的空间,则不用prebuffer
				bytesToRead = [currentRead readLengthForTermWithHint:estimatedBytesAvailable
				                                     shouldPreBuffer:&readIntoPreBuffer];
			}
            
			else
			{
				// Read type #1 or #2
				//直接读这个长度,如果到maxlength,就用maxlength
				bytesToRead = [currentRead readLengthForNonTermWithHint:estimatedBytesAvailable];
			}
			
            //大于最大值,则先读最大值
			if (bytesToRead > SIZE_MAX) { // NSUInteger may be bigger than size_t (read param 3)
				bytesToRead = SIZE_MAX;
			}
			
			// Make sure we have enough room in the buffer for our read.
			//
			// We are either reading directly into the currentRead->buffer,
			// or we're reading into the temporary preBuffer.
			
			if (readIntoPreBuffer)
			{
				[preBuffer ensureCapacityForWrite:bytesToRead];
				
				buffer = [preBuffer writeBuffer];
			}
			else
			{
				[currentRead ensureCapacityForAdditionalDataOfLength:bytesToRead];
				
				buffer = (uint8_t *)[currentRead->buffer mutableBytes]
				       + currentRead->startOffset
				       + currentRead->bytesDone;
			}
			
			// Read data into buffer
			
			int socketFD = (socket4FD != SOCKET_NULL) ? socket4FD : (socket6FD != SOCKET_NULL) ? socket6FD : socketUN;
#pragma mark - 开始读取数据,最普通的形式 read
            
            //读数据
			ssize_t result = read(socketFD, buffer, (size_t)bytesToRead);
			LogVerbose(@"read from socket = %i", (int)result);
            //读取错误
			if (result < 0)
			{
                //EWOULDBLOCK IO阻塞
				if (errno == EWOULDBLOCK)
                    //先等待
					waiting = YES;
				else
                    //得到错误
					error = [self errnoErrorWithReason:@"Error in read() function"];
				//把可读取的长度设置为0
				socketFDBytesAvailable = 0;
			}
            //读到边界了
			else if (result == 0)
			{
				socketEOF = YES;
				socketFDBytesAvailable = 0;
			}
            //正常
			else
			{
                //设置读到的数据长度
				bytesRead = result;
				
                //如果读到的数据小于应该读的长度,说明这个包没读完
				if (bytesRead < bytesToRead)
				{
					// The read returned less data than requested.
					// This means socketFDBytesAvailable was a bit off due to timing,
					// because we read from the socket right when the readSource event was firing.
					socketFDBytesAvailable = 0;
				}
                //正常
				else
				{
                    //如果 socketFDBytesAvailable比读了的数据小的话,直接置为0
					if (socketFDBytesAvailable <= bytesRead)
						socketFDBytesAvailable = 0;
                    //减去已读大小
					else
						socketFDBytesAvailable -= bytesRead;
				}
				//如果 socketFDBytesAvailable 可读数量为0,把读的状态切换为等待
				if (socketFDBytesAvailable == 0)
				{
					waiting = YES;
				}
			}
		}
		
        //如果这次读的字节大于0
		if (bytesRead > 0)
		{
			// Check to see if the read operation is done
			//检查这个包的数据是否读完,用readLength来读的
			if (currentRead->readLength > 0)
			{
				// Read type #2 - read a specific length of data
				// 
				// Note: We should never be using a prebuffer when we're reading a specific length of data.
                //我们读取固定大小的时候是永远不用写到prebuffer中去的
                
				//断言,是不需要写到prebuffer中去的
				NSAssert(readIntoPreBuffer == NO, @"Invalid logic");
				
                //加上读的数量
				currentRead->bytesDone += bytesRead;
                //把这一次读的数量加上来
				totalBytesReadForCurrentRead += bytesRead;
				//判断是否已读完
				done = (currentRead->bytesDone == currentRead->readLength);
			}
            
            //用边界来读的
			else if (currentRead->term != nil)
			{
				// Read type #3 - read up to a terminator
				//如果是往buffer中读的
				if (readIntoPreBuffer)
				{
					// We just read a big chunk of data into the preBuffer
					
                    //移动writeBuffer的指针
					[preBuffer didWrite:bytesRead];
					LogVerbose(@"read data into preBuffer - preBuffer.length = %zu", [preBuffer availableBytes]);
					
					// Search for the terminating sequence
					
                    //拿到需要读取的大小,根据term,并且判断是否已读完
					NSUInteger bytesToCopy = [currentRead readLengthForTermWithPreBuffer:preBuffer found:&done];
					LogVerbose(@"copying %lu bytes from preBuffer", (unsigned long)bytesToCopy);
					
					// Ensure there's room on the read packet's buffer
					//确保有这么大的空间
					[currentRead ensureCapacityForAdditionalDataOfLength:bytesToCopy];
					
					// Copy bytes from prebuffer into read buffer
					
					uint8_t *readBuf = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset
					                                                                 + currentRead->bytesDone;
					
#pragma mark - 把数据从preBuffer中移到currentRead上
					memcpy(readBuf, [preBuffer readBuffer], bytesToCopy);
					
					// Remove the copied bytes from the prebuffer
                    //标记已经读了这么多数据
					[preBuffer didRead:bytesToCopy];
					LogVerbose(@"preBuffer.length = %zu", [preBuffer availableBytes]);
					
					// Update totals
					currentRead->bytesDone += bytesToCopy;
					totalBytesReadForCurrentRead += bytesToCopy;
					
					// Our 'done' variable was updated via the readLengthForTermWithPreBuffer:found: method above
				}
                
                //没有用prebuffer
				else
				{
					// We just read a big chunk of data directly into the packet's buffer.
					// We need to move any overflow into the prebuffer.
					//我们需要把数据流向prebuffer?
                    
                    //拿到粘包长度,(为溢出长度,溢出的我们要写到prebuffer中去。给下一个包去读)
					NSInteger overflow = [currentRead searchForTermAfterPreBuffering:bytesRead];
					
                    //如果为0,说明完全匹配
					if (overflow == 0)
					{
						//加上这次读取的字节数
						currentRead->bytesDone += bytesRead;
                        //总的读取字节数
						totalBytesReadForCurrentRead += bytesRead;
                        //标志读取完成
						done = YES;
					}
                    
                    //说明读取的数据总长度比当前包大(粘包)
					else if (overflow > 0)
					{
						
                        //当前包内的长度
						NSInteger underflow = bytesRead - overflow;
						
						// Copy excess data into preBuffer
						
						LogVerbose(@"copying %ld overflow bytes into preBuffer", (long)overflow);
                        //确保preBuffer有这么大的大小
						[preBuffer ensureCapacityForWrite:overflow];
						
                        //把buffer往后移,去掉重合的数据大小
						uint8_t *overflowBuffer = buffer + underflow;
                        
                        //写到writeBuffer中,长度为 overflow(非重合部分)
						memcpy([preBuffer writeBuffer], overflowBuffer, overflow);
						//后移写指针
						[preBuffer didWrite:overflow];
						LogVerbose(@"preBuffer.length = %zu", [preBuffer availableBytes]);
						
						// Note: The completeCurrentRead method will trim the buffer for us.
						
                        //加上已读的大小(非粘包的)
						currentRead->bytesDone += underflow;
                        //这次总共读取的大小
						totalBytesReadForCurrentRead += underflow;
                        //当前读取完成
						done = YES;
					}
                    //数据还没达到边界
					else
					{
						// The term was not found within the data that we read.
						//已读的加上 bytesRead
						currentRead->bytesDone += bytesRead;
						totalBytesReadForCurrentRead += bytesRead;
                        //标记为未完成
						done = NO;
					}
				}
				
                //如果未完成 而且当前包的数据包最大长度大于0
				if (!done && currentRead->maxLength > 0)
				{
					// We're not done and there's a set maxLength.
					// Have we reached that maxLength yet?
					//判断写的大小 是否达到包的最大值
					if (currentRead->bytesDone >= currentRead->maxLength)
					{
                        //得到读取溢出的错误
						error = [self readMaxedOutError];
					}
				}
			}
            
            //没边界,没给定长度(无法判断当前包结尾)
			else
			{
				// Read type #1 - read all available data
				//如果从prebuffer中读取
				if (readIntoPreBuffer)
				{
					// We just read a chunk of data into the preBuffer
					
                    //指针后移
					[preBuffer didWrite:bytesRead];
					
					// Now copy the data into the read packet.
					// 
					// Recall that we didn't read directly into the packet's buffer to avoid
					// over-allocating memory since we had no clue how much data was available to be read.
					// 
					// Ensure there's room on the read packet's buffer
					
                    //确保currentRead中有bytesRead大小可用
					[currentRead ensureCapacityForAdditionalDataOfLength:bytesRead];
					
					// Copy bytes from prebuffer into read buffer
					
					uint8_t *readBuf = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset
					                                                                 + currentRead->bytesDone;
					
                    //拿到指针赋值
					memcpy(readBuf, [preBuffer readBuffer], bytesRead);
					
					// Remove the copied bytes from the prebuffer
					//标记读了这么多数据
                    [preBuffer didRead:bytesRead];
					
					// Update totals
                    //更新已读
					currentRead->bytesDone += bytesRead;
					totalBytesReadForCurrentRead += bytesRead;
				}
                //在currentRead中的话直接加就行
				else
				{
					currentRead->bytesDone += bytesRead;
					totalBytesReadForCurrentRead += bytesRead;
				}
				//因为无法判断结尾,所以每次读都会直接标记为YES,即一个包完成
				done = YES;
			}
			
		} // if (bytesRead > 0)
		
	} // if (!done && !error && !socketEOF && hasBytesAvailable)
	
	
    //如果未完成,而且没有应读长度和边界符
	if (!done && currentRead->readLength == 0 && currentRead->term == nil)
	{
		// Read type #1 - read all available data
		// 
		// We might arrive here if we read data from the prebuffer but not from the socket.
		//只要当前总共读的数量大于0,就认为完成了,因为无从判断
		done = (totalBytesReadForCurrentRead > 0);
	}
	
	// Check to see if we're done, or if we've made progress
	//检查是否读完
	if (done)
	{
        //完成这次数据的读取
		[self completeCurrentRead];
		//如果没出错,没有到边界,prebuffer中还有可读数据
		if (!error && (!socketEOF || [preBuffer availableBytes] > 0))
		{
            //让读操作离队,继续进行下一次读取
			[self maybeDequeueRead];
		}
	}
    
    //如果这次读的数量大于0
	else if (totalBytesReadForCurrentRead > 0)
	{
		// We're not done read type #2 or #3 yet, but we have read in some bytes

		__strong id theDelegate = delegate;
		
        //如果响应读数据进度的代理
		if (delegateQueue && [theDelegate respondsToSelector:@selector(socket:didReadPartialDataOfLength:tag:)])
		{
			long theReadTag = currentRead->tag;
			
            //代理queue中回调出去
			dispatch_async(delegateQueue, ^{ @autoreleasepool {
				
				[theDelegate socket:self didReadPartialDataOfLength:totalBytesReadForCurrentRead tag:theReadTag];
			}});
		}
	}
	
	// Check for errors
	//检查错误
	if (error)
	{
        //如果有错直接报错断开连接
		[self closeWithError:error];
	}
    //如果是读到边界错误
	else if (socketEOF)
	{
		[self doReadEOF];
	}
    
    //如果是等待
	else if (waiting)
	{
        //如果用的是CFStream,则读取数据和source无关
        //非CFStream形式
		if (![self usingCFStreamForTLS])
		{
			// Monitor the socket for readability (if we're not already doing so)
            //重新恢复source
			[self resumeReadSource];
		}
	}
	// Do not add any code here without first adding return statements in the error cases above.
}

特别特别长...接下来就是关闭socket了

5.CLOSE
- (void)closeWithError:(NSError *)error
{
	LogTrace();
    //先判断当前queue是不是IsOnSocketQueueOrTargetQueueKey
	NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
	
    //关闭连接超时
	[self endConnectTimeout];
	
	if (currentRead != nil)  [self endCurrentRead];
	if (currentWrite != nil) [self endCurrentWrite];
	
	[readQueue removeAllObjects];
	[writeQueue removeAllObjects];
	
	[preBuffer reset];
	
	#if TARGET_OS_IPHONE
	{
		if (readStream || writeStream)
		{
			[self removeStreamsFromRunLoop];
			
			if (readStream)
			{
				CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL);
				CFReadStreamClose(readStream);
				CFRelease(readStream);
				readStream = NULL;
			}
			if (writeStream)
			{
				CFWriteStreamSetClient(writeStream, kCFStreamEventNone, NULL, NULL);
				CFWriteStreamClose(writeStream);
				CFRelease(writeStream);
				writeStream = NULL;
			}
		}
	}
	#endif
	
	[sslPreBuffer reset];
	sslErrCode = lastSSLHandshakeError = noErr;
	
	if (sslContext)
	{
		// Getting a linker error here about the SSLx() functions?
		// You need to add the Security Framework to your application.
		//关闭sslContext
		SSLClose(sslContext);
		
		#if TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
		CFRelease(sslContext);
		#else
		SSLDisposeContext(sslContext);
		#endif
		
		sslContext = NULL;
	}
	
	// For some crazy reason (in my opinion), cancelling a dispatch source doesn't
	// invoke the cancel handler if the dispatch source is paused.
	// So we have to unpause the source if needed.
	// This allows the cancel handler to be run, which in turn releases the source and closes the socket.
	
    //如果这些source都为空,直接只关闭socket就可以
	if (!accept4Source && !accept6Source && !acceptUNSource && !readSource && !writeSource)
	{
		LogVerbose(@"manually closing close");

		if (socket4FD != SOCKET_NULL)
		{
			LogVerbose(@"close(socket4FD)");
			close(socket4FD);
			socket4FD = SOCKET_NULL;
		}

		if (socket6FD != SOCKET_NULL)
		{
			LogVerbose(@"close(socket6FD)");
			close(socket6FD);
			socket6FD = SOCKET_NULL;
		}
		
		if (socketUN != SOCKET_NULL)
		{
			LogVerbose(@"close(socketUN)");
			close(socketUN);
			socketUN = SOCKET_NULL;
            //断开Unix domin socket
			unlink(socketUrl.path.fileSystemRepresentation);
			socketUrl = nil;
		}
	}
	else
	{
        //都去取消souce先
		if (accept4Source)
		{
			LogVerbose(@"dispatch_source_cancel(accept4Source)");
			dispatch_source_cancel(accept4Source);
			
			// We never suspend accept4Source
			
			accept4Source = NULL;
		}
		
		if (accept6Source)
		{
			LogVerbose(@"dispatch_source_cancel(accept6Source)");
			dispatch_source_cancel(accept6Source);
			
			// We never suspend accept6Source
			
			accept6Source = NULL;
		}
		
		if (acceptUNSource)
		{
			LogVerbose(@"dispatch_source_cancel(acceptUNSource)");
			dispatch_source_cancel(acceptUNSource);
			
			// We never suspend acceptUNSource
			
			acceptUNSource = NULL;
		}
	
        //读写source需要resume,否则如果是suspend状态的话,cancel不会被调用
		if (readSource)
		{
			LogVerbose(@"dispatch_source_cancel(readSource)");
			dispatch_source_cancel(readSource);
			
			[self resumeReadSource];
			
			readSource = NULL;
		}
		
		if (writeSource)
		{
			LogVerbose(@"dispatch_source_cancel(writeSource)");
			dispatch_source_cancel(writeSource);
			
			[self resumeWriteSource];
			
			writeSource = NULL;
		}
		
		// The sockets will be closed by the cancel handlers of the corresponding source
		socket4FD = SOCKET_NULL;
		socket6FD = SOCKET_NULL;
		socketUN = SOCKET_NULL;
	}
	
	// If the client has passed the connect/accept method, then the connection has at least begun.
	// Notify delegate that it is now ending.
    //判断是否sokcet开启
	BOOL shouldCallDelegate = (flags & kSocketStarted) ? YES : NO;
	BOOL isDeallocating = (flags & kDealloc) ? YES : NO;
	
	// Clear stored socket info and all flags (config remains as is)
    //清楚socket的相关信息,和所有标记
	socketFDBytesAvailable = 0;
	flags = 0;
	sslWriteCachedLength = 0;
	
	if (shouldCallDelegate)
	{
		__strong id theDelegate = delegate;
        //判断是否需要传自己过去,如果已经被销毁,就传nil
		__strong id theSelf = isDeallocating ? nil : self;
		
        //调用断开连接的代理
		if (delegateQueue && [theDelegate respondsToSelector: @selector(socketDidDisconnect:withError:)])
		{
			dispatch_async(delegateQueue, ^{ @autoreleasepool {
				
				[theDelegate socketDidDisconnect:theSelf withError:error];
			}});
		}	
	}
}