OGeek|极客世界-中国程序员成长平台

标题: ios - NSURLSession 多个并发请求被 Exchange 服务器拒绝 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-12 13:18
标题: ios - NSURLSession 多个并发请求被 Exchange 服务器拒绝

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

{
"s:Envelope" =     {
    "s:Body" =         {
        "m:GetItemResponse" =             {
            "m:ResponseMessages" =                 {
                "m:GetItemResponseMessage" =                     {
                    ResponseClass = Error;
                    "mescriptiveLinkKey" =                         {
                        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)URLSessionNSURLSession *)session
     dataTaskNSURLSessionDataTask *)dataTask
   didReceiveDataNSData *)data
{
    [self.data appendData:data];
}

-(void)URLSessionNSURLSession *)session
             taskNSURLSessionTask *)task
didCompleteWithErrorNSError *)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];
    }
});

我认为我的问题是我在每次通话时都在进行 session ,但我不知道看到其他方式。

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

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



Best Answer-推荐答案


为了尽量减少架构更改,我可能会建议使用单例来管理 session ,但代理对相关对象的委托(delegate)调用。换句话说:

  1. 使用 NSURLRequest 调用该单例类的方法并让它创建任务;也将您的 HTTPRequest 对象传递给该方法,以便它知道该调用谁来处理结果。
  2. 在单例类中,将新创建的 NSURLSession[Data|Download|Upload]Task 对象作为键存储在字典中。
  3. 将您的 HTTPRequest 对象存储为相应的值。
  4. 编写一大堆每个任务的委托(delegate)方法,每个方法在字典中查找任务并在正确的 HTTPRequest 对象上调用相同的委托(delegate)方法。
  5. 任务完成后,将其从字典中移除以释放 HTTPRequest 对象。

或者,如果所有 HTTPRequest 对象确实在做的是提供一堆身份验证处理方法并积累数据,您可以考虑创建一个接受 NSURLRequest 的单例类> 取而代之的是一个对象和一个 block ,并在您获取数据时运行该 block 。

就此而言,如果您不以增量方式处理数据,您也可以考虑将该 block 直接作为任务的 completionHandler block 传递,并让 session 本身处理数据累积。

关于ios - NSURLSession 多个并发请求被 Exchange 服务器拒绝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43393131/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://ogeek.cn/) Powered by Discuz! X3.4