Ios NSURLSession Exchange server拒绝了多个并发请求

Ios NSURLSession Exchange server拒绝了多个并发请求,ios,concurrency,exchangewebservices,nsurlsession,Ios,Concurrency,Exchangewebservices,Nsurlsession,我已将我的NSURLConnection代码替换为nsursession,以便使用EWS Exchange server获取数据。我的应用程序进行多个并发API调用。它工作正常,但现在,当我使用NSURLSession时,我的一些API调用得到了正确的响应,一些API调用从exchange server得到错误,如下所示: { "s:Envelope" = { "s:Body" = { "m:GetItemResponse" =

我已将我的
NSURLConnection
代码替换为
nsursession
,以便使用EWS Exchange server获取数据。我的应用程序进行多个并发API调用。它工作正常,但现在,当我使用
NSURLSession
时,我的一些API调用得到了正确的响应,一些API调用从exchange server得到错误,如下所示:

{
"s:Envelope" =     {
    "s:Body" =         {
        "m:GetItemResponse" =             {
            "m:ResponseMessages" =                 {
                "m:GetItemResponseMessage" =                     {
                    ResponseClass = Error;
                    "m:DescriptiveLinkKey" =                         {
                        text = 0;
                    };
                    "m:Items" =                         {
                    };
                    "m:MessageText" =                         {
                        text = "An internal server error occurred. The operation failed., Cannot open mailbox /o=First Organization/ou=Exchange Administrative Group(FYDIBOHF23SPDLT)/cn=Recipients/cn=00037FFEE6F0D3D2.";
                    };
                    "m:MessageXml" =                         {
                        "t:Value" =                             (
                                                            {
                                Name = InnerErrorMessageText;
                                text = "Too many concurrent connections opened.";
                            },
                                                            {
                                Name = InnerErrorResponseCode;
                                text = ErrorTooManyObjectsOpened;
                            },
                                                            {
                                Name = InnerErrorDescriptiveLinkKey;
                                text = 0;
                            }
                        );
                    };
                    "m:ResponseCode" =                         {
                        text = ErrorInternalServerError;
                    };
                };
            };
            "xmlns:m" = "http://schemas.microsoft.com/exchange/services/2006/messages";
            "xmlns:t" = "http://schemas.microsoft.com/exchange/services/2006/types";
        };
        "xmlns:xsd" = "http://www.w3.org/2001/XMLSchema";
        "xmlns:xsi" = "http://www.w3.org/2001/XMLSchema-instance";
    };
    "s:Header" =         {
        "h:ServerVersionInfo" =             {
            MajorBuildNumber = 1034;
            MajorVersion = 15;
            MinorBuildNumber = 11;
            MinorVersion = 1;
            xmlns = "http://schemas.microsoft.com/exchange/services/2006/types";
            "xmlns:h" = "http://schemas.microsoft.com/exchange/services/2006/types";
            "xmlns:xsd" = "http://www.w3.org/2001/XMLSchema";
            "xmlns:xsi" = "http://www.w3.org/2001/XMLSchema-instance";
        };
    };
    "xmlns:s" = "http://schemas.xmlsoap.org/soap/envelope/";
};
显然,问题是同时连接太多

我的代码流是:

我的
HTTPRequest.m
有一个方法

- (void)fetchData
{
    dispatch_async(dispatch_get_main_queue(), ^{

        sessionAlive = sessionAlive + 1;

        NSLog(@"sessionCount: %ld", (long)sessionAlive);

        NSURLSessionConfiguration *defaultConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration];

        NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfiguration
                                                                     delegate:self
                                                               delegateQueue:nil];

        NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:request];

        [dataTask resume];
    });
}

// Some NSURLSession delegates methods here

-(void)URLSession:(NSURLSession *)session
     dataTask:(NSURLSessionDataTask *)dataTask
   didReceiveData:(NSData *)data
{
    [self.data appendData:data];
}

-(void)URLSession:(NSURLSession *)session
             task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
    if (error)
    {
        self.failureBlock ? self.failureBlock(error) : nil;
    }
    else
    {
        NSData *data;

        if (self.data)
        {
            data = [NSData dataWithData:self.data];
        }

        self.successBlock ? self.successBlock(self.redirectLocation, data) : nil;
    }

    [session finishTasksAndInvalidate]; // We must release the session, else it holds strong referance for it's delegate (in our case EWSHTTPRequest).
                                        // And it wont allow the delegate object to free -> cause memory leak
}
我正在同时下载类似这样的电子邮件:

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

dispatch_async(backgroundQueue, ^{

foreach (NSString *emailId in emalilIDArray)
    {
     HTTPRequest *request = [HTTPRequest alloc] init];
      [request fetchData];
    }
});
我想我的问题是每次打电话我都会打电话,但我不知道该怎么办

如果我不能使用共享实例会话,因为我需要将会话的委托与每个HTTPRequest对象关联以处理响应


有什么建议或更好的方法吗?

为了最大限度地减少体系结构的更改,我可能会建议使用一个单例来管理会话,但代理对相关对象的委托调用。换言之:

  • 使用
    NSURLRequest
    对该单例类调用一个方法,并让它创建任务;将您的
    HTTPRequest
    对象也传递给该方法,以便它知道使用结果调用谁
  • 在singleton类中,将新创建的
    NSURLSession[Data | Download | Upload]任务
    对象作为键存储在字典中
  • HTTPRequest
    对象存储为相应的值
  • 编写一大堆每个任务的委托方法,每个方法在字典中查找任务,并在正确的
    HTTPRequest
    对象上调用相同的委托方法
  • 任务完成后,将其从字典中删除以释放
    HTTPRequest
    对象
  • 另一方面,如果所有的<代码> HTTPRequest < /Cord>对象正在做的是提供一组身份验证处理方法并积累数据,您可以考虑创建一个Stutelon类,该类使用一个<代码> NSURLRequest <代码>对象和一个块,并在您获得数据时运行该块。


    因此,如果不以增量方式处理数据,您还可以考虑将该块直接作为任务的 CultTyOnHelds块,并让会话本身处理数据累积。

    < P>您可以使用尽可能多的会话,但是如果您创建太多的连接到服务器,我将提供:

    它需要在一些单例中为您的请求提供共享操作队列,但 代替使用GCD中的主或全局操作队列考虑NSO操作队列和NS操作的使用。NSOperationQueue可以对可同时执行的任务数进行限制

    var operationCount:Int队列中当前的操作数

    因此,您可以限制同时连接的数量。 据我所知,dispatch_get_global_队列不具有这种可能性,因为您只使用外部现有队列,无法为其分配限制

    所以不是

    dispatch_async(backgroundQueue, ^{...
    
    您可以使用相同的块创建NSBlockOperation,并将此操作添加到NSOperationQueue。如果您添加的任务超过“operationCount”,则只会发出“operationCount”请求。所有其他人将在其中一个已执行任务完成时等待

    这不是完整的代码,而是您可以尝试的想法

     NSOperationQueue *backgroundOperationQueue = [[NSOperationQueue alloc] init];
     backgroundOperationQueue.operationCount = 5;
     NSOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:yourblock];
    [backgroundOperationQueue addOperation:blockOperation];
    

    如果你喜欢GCD,考虑使用串行队列,它只允许一个任务在时间。< /P>

    dispatch_queue_t queue;
    queue = dispatch_queue_create("com.example.MyQueue", NULL);