Докачивание файлов по HTTP при разрыве соединения

Сеть в Unity3D

Докачивание файлов по HTTP при разрыве соединения

Сообщение Inessa 10 ноя 2016, 15:42

Я реализовала метод для докачивания файлов по HTTP при разрыве соединения.

При тестировании этого метода в консольном приложении Visual Studio результат положительный.

При попытке использования этого метода в тестовом проекте в Unity происходит непонятное "зависание", когда выполнение доходит до оператора:

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()),

а затем происходит зависание, причину которого я никак не могу выяснить даже при установке точки останова (breakpoint) на этом операторе во время отладки.

Причем этот блок using у меня обрамлен конструкцией try-catch с обработкой соответствующих исключений, но во время выполнения никакого исключения не возникает.

Вот используемый мною класс с загрузчиком файлов по HTTP с возможностью докачки при разрыве соединения.

Синтаксис:
Используется csharp
namespace SceneDownloader
{
    using UnityEngine;
    using System;
    using System.IO;
    using System.Net;

    public class FileDownloader : MonoBehaviour
    {
        static int bufferSize = 1024 * 1000;
        static long offset = 0L;

        public static void DownloadSingleFile(string sourceURL, string destinationPath)
        {
            try
            {
                if (File.Exists(destinationPath))
                {
                    FileInfo fileInfo = new FileInfo(destinationPath);
                    offset = fileInfo.Length;
                }

                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(sourceURL);
                request.AddRange((int)offset);

                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    Stream source = response.GetResponseStream();
                    if (source != null)
                    {
                        byte[] buffer = new byte[bufferSize];
                        using (FileStream fileStream = new FileStream(destinationPath, FileMode.OpenOrCreate, FileAccess.Write))
                        {
                            fileStream.Position = offset;
                            while (true)
                            {
                                int readed = source.Read(buffer, 0, buffer.Length);
                                if (readed == 0) break;

                                fileStream.Write(buffer, 0, readed);
                            } // while (true)
                        } // using (FileStream fileStream
                    } // if (source != null)
                } // using (HttpWebResponse response)
            } // try
            catch (WebException ex)
            {
                Debug.Log("Trying to connect (check your connection)...");
                DownloadSingleFile(sourceURL, destinationPath);
            } // catch (WebException ex)
            catch (IOException ex)
            {
                Debug.Log("Trying to connect (check your connection)...");
                DownloadSingleFile(sourceURL, destinationPath);
            } // catch (IOException ex)
            catch (Exception ex)
            {
                Debug.Log("Trying to connect (check your connection)...");
                DownloadSingleFile(sourceURL, destinationPath);
            } // catch (Exception ex)
        } // public static void DownloadSingleFile
    } // public class FileDownloader
} // namespace SceneDownloader
 


Скажите, по какой причине может происходить это непонятное "зависание" при вызове метода загрузки файла по HTTP из скрипта в Unity?

Я, может быть, повторюсь, но этот же код отлично работает при его тестировании из консольного приложения в Visual Studio.

Как мне исправить возникшую проблему?
Inessa
UNITрон
 
Сообщения: 160
Зарегистрирован: 13 мар 2013, 11:56

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение DbIMok 10 ноя 2016, 15:58

что такое "зависание"? выполнение программы останавливается на какое-то время или вообще? если первое, то вероятно операция синхронная. то есть послали вы запрос и ожидаете ответ. и пока ответ не придет, ничего больше (в этом потоке) не выполняется. уверен, точно так же "отлично" работает и в консоли. выносите в отдельный поток или используйте что-нибудь асинхронное.
правильный вопрос - половина ответа. учитесь формулировать вопросы понятно.
Новости > _Telegram чат @unity3d_ru (11.6k/4.8k online) > _Telegram канал @unity_news (4.7k подписчиков) > Телеграм тема > "Спасибо"
Аватара пользователя
DbIMok
Адепт
 
Сообщения: 6372
Зарегистрирован: 31 июл 2009, 14:05

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение Inessa 10 ноя 2016, 17:05

Под "зависанием" я имею в виду, что отклик от тестируемого мной проекта во время запуска на исполнение пропадает ВООБЩЕ при обращенит к оператору:

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())

По какой-то причине при вызове метода (HttpWebResponse)request.GetResponse()) из Unity объект request не возвращает никакого результата из-за чего и происходит "зависание".

Я добавила перед вызовом этого метода тайм-аут (10 сек) для ожидания ответа от сервера:

request.Timeout = 10000;

В этом случае по истечению тайм-аута возникает исключение WebException, которое я обрабатываю в блоке try-catch.

Мне нужно сначала "разобраться" с синхронной загрузкой хотя бы одного файла, а затем уже перейти к реализации асинхронной загрузки для нескольких файлов.

Таким образом, СЕЙЧАС у меня при запуске данного кода из редактора Unity метод загрузчика пытается "достучаться" до сервера в течении 10 сек, а затем возникает исключение WebException.

В консольном приложении Visual Studio этот же код нормально связывается с сервером и загружает файл без всяких исключений.

Может быть при работе в Unity у меня закрыты какие-нибудь порты или файервол "режет" соединение?

Тогда почему консольное приложение в Visual Studio с этим же кодом не испытывает никаких проблем с портами и фаерволом?

Для выяснения этой проблемы я сделала следующее.

Создала в настройках своего фаервола для исполняемого файла Unity.exe разрешение для осуществления ЛЮБЫХ сетевых действий в ЛЮБОМ направлении по протоколу TCP & UDP при работе по 80-му порту(HTTP).

Но это не помогло!

Скажите, почему при запуске тестируемого мной скрипта из Unity тестируемый проект не может получить отклик от сервера в течении заданного тайм-аута?

Проблема явно не на стороне сервера, т.к. консольное приложение работает безо всяких проблем.

В чем тут может быть дело, и как можно исправить эту ситуацию?
Inessa
UNITрон
 
Сообщения: 160
Зарегистрирован: 13 мар 2013, 11:56

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение ikhtd 10 ноя 2016, 17:40

то что связано с докачкой файлов - тут еще может зависит от настройки сервака. он может не отдавать информацию - например сколько мегабайт скачано или отдавать но не всем - или отдавать не для всех типов файлов. к примеру у меня сайт привязан к клаудфлер - у них nginx и информацию о ходе загрузки файла они отдадут только для картинок. а для произвольного типа файла просто не получишь запрос. хотя VS он у вас отдает 100 проц.
Скрытый текст:
Объективная реальность это - что в жизни не может быть более одного пути, который в свою очередь обусловлен максимальным существующим давлением. (второй _ttp://habrahabr.ru/post/202654/)
ikhtd
Адепт
 
Сообщения: 1124
Зарегистрирован: 24 мар 2014, 12:20

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение Inessa 10 ноя 2016, 18:53

При запуске моего тестового проекта на мобильных устройствах, работающих под управлением Android, в протоколе Logcat выводится ошибка:

Unable to find /System/Library/Frameworks/Security.framework/Security,

т.е. возникающее в коде исключение типа WebException обусловлено именно этой ошибкой.

В интернете советуют перед осуществлением запроса вставить в код строку со следующим кодом:

ServicePointManager.ServerCertificateValidationCallback = (p1, p2, p3, p4) => true;

Правда, в моем случае этот совет не помог - значит дело в чем-то другом?

В одной и найденных мною в интернете тем на другом форуме

Android Unable to find /System/Library/Frameworks/Security.framework/Security
http://answers.unity3d.com/questions/52 ... ssecu.html

советуют еще исследовать проблему с проверкой сертификатов как это описано в

Bug 6501 - Unexpected invalid certificate exception
https://bugzilla.xamarin.com/show_bug.cgi?id=6501

Я не очень разбираюсь в теме с проверкой сертификатов.

Подскажите, пожалуйста, что нужно сделать в моем случае, если проблема все-таки с этими сертификатами раз уж под Android-ом вылазит такая ошибка?
Inessa
UNITрон
 
Сообщения: 160
Зарегистрирован: 13 мар 2013, 11:56

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение ikhtd 10 ноя 2016, 19:15

вы в редакторе переменную fileInfo не получаете?

Security это связано с доступом. только отключение файревола не поможет. сертификат проверять только если используется https адрес- у вас наверно просто http.
У вас сервак apache? это хостинг или VPS?
Скрытый текст:
Объективная реальность это - что в жизни не может быть более одного пути, который в свою очередь обусловлен максимальным существующим давлением. (второй _ttp://habrahabr.ru/post/202654/)
ikhtd
Адепт
 
Сообщения: 1124
Зарегистрирован: 24 мар 2014, 12:20

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение Inessa 10 ноя 2016, 19:51

Переменную fileInfo я использую только в вышеприведенном скрипте и больше нигде.

Это может иметь какое-то значение?

В качестве хостинга я использую сервис Google App Engine, на котором я создала на Java свое веб-приложение (сайт для игры).

В одной из папок сайта я храню файлы для скачивания с этого удаленного хостинга.

В своем тестовом проекте я использовала в указании пути к файлам - HTTPS.

После того, как я поменяла СЕЙЧАС путь к файлам на HTTP ошибка

Unable to find /System/Library/Frameworks/Security.framework/Security

при запуске проекта под Android в протоколе Logcat исчезла.

Однако отклик по истечению заданного тайм-аута в ходе вызова метода загрузки файла с удаленного хостинга не происходит.

Я по прежнему перехватываю исключение WebException при запуске тестового проекта из редактора и на мобильном устройстве.

Мне кажется, что возникающая ситуация связана как-то с Unity, т.к. в Visual Studio все работает отлично.

Только как определить причину по которой возникает WebException при попытке обращения к удаленному хостингу с использованием этого же программного кода из Unity?
Inessa
UNITрон
 
Сообщения: 160
Зарегистрирован: 13 мар 2013, 11:56

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение ikhtd 10 ноя 2016, 22:15

Я не знаю в чем отличие доступа к VS от доступа к редактору, но судя по всему настраивать сервер у вас нет возможности, потому что это какой то сервис, а не ваш VPS. Значит в любом случае расширить доступ к файлам вы на том сервере не сможете. Про fileinfo в редакторе я спрашивал, потому что если вы получаете там инфу из этого файла- значит в редакторе с доступом к fileinfo нормально.
Можете попробовать работать с моим файлом, он точно имеет доступ. Это бандл (u5.4) с расширением .jpg, fileinfo в редактор он отдает, это проверено. а кстати на гугл хостинге например бандлы не пашут, даже если билд на том же гугл хостинге -доступы режут.
http://toyourleader.com/mybundle/myshop.jpg
Скрытый текст:
Объективная реальность это - что в жизни не может быть более одного пути, который в свою очередь обусловлен максимальным существующим давлением. (второй _ttp://habrahabr.ru/post/202654/)
ikhtd
Адепт
 
Сообщения: 1124
Зарегистрирован: 24 мар 2014, 12:20

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение Inessa 11 ноя 2016, 00:03

Мне кажется я поняла в чем было дело.

На этом сервисе Google App Engine есть какие-то квоты на количество запросов, которые я быстро исчерпала "заставив" свой тестовый проект постоянно стучаться на сервер по истечению тайм-аута.

По крайней мере, теперь понятно, что чтобы не было бесконечного "зависания" нужно задавать конечное значение тайм-аута в запросе.

Однако, я не могу понять следующее.

Почему при обработке исключений в моем скрипте мне не удается получить значение поля Message или методу ToString(), когда срабатывает один из блоков catch?

Вот, например, когда я в методе Debug.Log (см. ниже) пытаюсь обратиться к содержимому отлавливаемого исключения (WebException ex), в окне QuickWatch во время отладки в Visual Studio выводится сообщение:

The identifier `ex` is not in the scope.

Т.е. исключение "ловится", но его содержимое находится вне контекста при обращении к полю Message или методу ToString().

По какой причине происходит эта ситуация и как ее исправить, чтобы я могла видеть "содержимое" исключения, а не фиксировать только сам факт его возникновения?

Синтаксис:
Используется csharp
catch (WebException ex)
{
   Debug.Log("WebException" + ex.Message);
   Debug.Log("WebException" + ex.ToString());
   DownloadSingleFile(sourceURL, destinationPath);
}
 
Inessa
UNITрон
 
Сообщения: 160
Зарегистрирован: 13 мар 2013, 11:56

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение ikhtd 11 ноя 2016, 13:58

переходите на местный слэнг. потому что ваши сообщения в стиле Льва Толстого никто не поймет.
Скрытый текст:
Объективная реальность это - что в жизни не может быть более одного пути, который в свою очередь обусловлен максимальным существующим давлением. (второй _ttp://habrahabr.ru/post/202654/)
ikhtd
Адепт
 
Сообщения: 1124
Зарегистрирован: 24 мар 2014, 12:20

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение Inessa 11 ноя 2016, 14:06

OK. Переформулирую последний вопрос.

Почему в приведенном мной скрипте в блокe catch исключения перехватываются, но получить детальные их описания мне не удается?
Inessa
UNITрон
 
Сообщения: 160
Зарегистрирован: 13 мар 2013, 11:56

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение Tolking 11 ноя 2016, 14:13

Синтаксис:
Используется csharp
try{
   DownloadSingleFile(sourceURL, destinationPath);
}
catch (WebException ex)
{
   Debug.Log("WebException" + ex.Message);
   Debug.Log("WebException" + ex.ToString());
}
Ковчег построил любитель, профессионалы построили Титаник.
Аватара пользователя
Tolking
Адепт
 
Сообщения: 2715
Зарегистрирован: 08 июн 2009, 18:22
Откуда: Тула

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение getAlex 11 ноя 2016, 14:38

Inessa писал(а):На этом сервисе Google App Engine есть какие-то квоты на количество запросов, которые я быстро исчерпала "заставив" свой тестовый проект постоянно стучаться на сервер по истечению тайм-аута.

Скорее всего это защита от ддос. Между "стучаться" добавьте какой-то промежуток во времени и наращивайте его после каждого повторного постукивания.
getAlex
Адепт
 
Сообщения: 1775
Зарегистрирован: 10 авг 2013, 18:30

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение DAC 15 ноя 2016, 12:28

1. Попробуйте использовать штатный для движка UnityWebRequest
2. Стучитесь не чаще, чем раз в секунду.
DAC
UNIт
 
Сообщения: 62
Зарегистрирован: 17 ноя 2009, 17:11
Откуда: Хабаровск

Re: Докачивание файлов по HTTP при разрыве соединения

Сообщение DbIMok 15 ноя 2016, 13:06

DAC писал(а):Попробуйте использовать штатный для движка UnityWebRequest

он умеет докачивать?
правильный вопрос - половина ответа. учитесь формулировать вопросы понятно.
Новости > _Telegram чат @unity3d_ru (11.6k/4.8k online) > _Telegram канал @unity_news (4.7k подписчиков) > Телеграм тема > "Спасибо"
Аватара пользователя
DbIMok
Адепт
 
Сообщения: 6372
Зарегистрирован: 31 июл 2009, 14:05


Вернуться в Сеть

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1