我有非常复杂的应用程序,它使用多种网络服务.其中一些是带宽要求和时间关键(例如SIP服务),一些更容忍互联网连接不良(例如电源点显示).
问题
现在存在饥饿问题(一个服务可以支配整个带宽).
接收数据很容易解决.计算每个服务的数据速率,应用程序将所需的数据速率发送到服务器,服务器控制传入数据的速度.
困难的问题是在发送数据时控制数据的速度.
对于原始套接字连接,这很容易.套接字输出流简单地由NSOutputStream的子类包装,它延迟流事件HasSpaceAvailable,具体取决于在某个时间单位中已经写入套接字的字节数.
题
问题是如何正确地使用NSURLSession?我可以为委托方法中提供的HTTP正文的输入流做同样的技巧:
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler
但是这种方法不会考虑HTTP帧(标题).对于某些将进行密集轮询的服务,HTTP帧可能是发送数据的重要部分.因此,要正确控制数据速率,应考虑HTTP帧.问题是没有API可以帮助控制整个HTTP协议的数据速率.我可以看到API,它只允许控制HTTP请求体的数据.
更新
我试过使用API needNewBodyStream,它不起作用. NSURLSession同步使用传递的流.任何将数据拆分成可能延迟发送的块的尝试都会导致一些奇怪的错误和请求根本不会被发送.
所以我正在寻找任何替代方案.回答提出的解决方案:NSURLProtocol自己的实现有很多缺点:
>许多复杂的代码,不会传递与我的NSURLSession实例相关的内容
>区分哪些服务的问题是哪个带宽桶分配请求
>这对整个应用程序有影响,我提供了一个框架
所以我仍在寻找更好的解决方案
解决方法
它似乎提供了可以写入底层套接字的字节数的手动控制(与用例相同).使用readData:读取输入正文数据流的一小部分.
/* Read minBytes,or at most maxBytes bytes and invoke the completion * handler on the sessions delegate queue with the data or an error. * If an error occurs,any outstanding reads will also fail,and new * read requests will error out immediately. */ - (void)readDataOfMinLength:(NSUInteger)minBytes maxLength:(NSUInteger)maxBytes timeout:(NSTimeInterval)timeout completionHandler:(void (^) (NSData * __nullable data,BOOL atEOF,NSError * __nullable error))completionHandler;
然后你可以使用writeData:将这个数据包写入你的套接字.
/* Write the data completely to the underlying socket. If all the * bytes have not been written by the timeout,a timeout error will * occur. Note that invocation of the completion handler does not * guarantee that the remote side has received all the bytes,only * that they have been written to the kernel. */ - (void)writeData:(NSData *)data timeout:(NSTimeInterval)timeout completionHandler:(void (^) (NSError * __nullable error))completionHandler;
我不确定它是否能用HTTPHeader解决你的问题.正文数据是不同的数据包.这听起来像是正确的道路.
希望它能帮到你.