CocoaAsyncSocket源码Write(总结篇 二)
下面是写入的三种方式
CFStreamForTLS
- SSL写的方式
if (hasNewDataToWrite)
{
//拿到buffer偏移位置
const uint8_t *buffer = (const uint8_t *)[currentWrite->buffer bytes]
+ currentWrite->bytesDone
+ bytesWritten;
//得到需要读的长度
NSUInteger bytesToWrite = [currentWrite->buffer length] - currentWrite->bytesDone - bytesWritten;
//如果大于最大值,就等于最大值
if (bytesToWrite > SIZE_MAX) // NSUInteger may be bigger than size_t (write param 3)
{
bytesToWrite = SIZE_MAX;
}
size_t bytesRemaining = bytesToWrite;
//循环值
BOOL keepLooping = YES;
while (keepLooping)
{
//最大写的字节数?
const size_t sslMaxBytesToWrite = 32768;
//得到二者小的,得到需要写的字节数
size_t sslBytesToWrite = MIN(bytesRemaining, sslMaxBytesToWrite);
//已写字节数
size_t sslBytesWritten = 0;
//将结果从buffer中写到socket上(经由了这个函数,数据就加密了)
result = SSLWrite(sslContext, buffer, sslBytesToWrite, &sslBytesWritten);
//如果写成功
if (result == noErr)
{
//buffer指针偏移
buffer += sslBytesWritten;
//加上些的数量
bytesWritten += sslBytesWritten;
//减去仍需写的数量
bytesRemaining -= sslBytesWritten;
//判断是否需要继续循环
keepLooping = (bytesRemaining > 0);
}
else
{
//IO阻塞
if (result == errSSLWouldBlock)
{
waiting = YES;
//得到缓存的大小(后续长度会被自己写到SSL缓存去)
sslWriteCachedLength = sslBytesToWrite;
}
else
{
error = [self sslError:result];
}
//跳出循环
keepLooping = NO;
}
} // while (keepLooping)
这里还有对残余数据的处理:是通过指针buffer获取我们的keepLooping
循环值,循环进行写入
//将结果从buffer中写到socket上(经由了这个函数,数据就加密了)
result = SSLWrite(sslContext, buffer, sslBytesToWrite, &sslBytesWritten);
- 普通socket写入
- 也做了完成判断
//判断是否完成
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
{
// We were unable to finish writing the data,
// so we're waiting for another callback to notify us of available space in the lower-level output buffer.
//如果不是等待 而且没有出错
if (!waiting && !error)
{
// This would be the case if our write was able to accept some data, but not all of it.
//这是我们写了一部分数据的情况。
//去掉可接受数据的标记
flags &= ~kSocketCanAcceptBytes;
//再去等读source触发
if (![self usingCFStreamForTLS])
{
[self resumeWriteSource];
}
}
//如果已写大于0
if (bytesWritten > 0)
{
// We're not done with the entire write, but we have written some bytes
__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];
}});
}
}
}
那么整个 CocoaAsyncSocket Wirte的解析就到这里完成了,当你读完前面几篇,再来看这篇就跟喝水一样,故:知识在于积累
由于该框架源码篇幅过大,且有大部分相对抽象的数据操作逻辑,尽管楼主竭力想要简单的去陈述相关内容,但是阅读起来仍会有一定的难度
作者:Cooci
链接:https://www.jianshu.com/p/dfacaf629571