В этой статье обобщаются причины сетевых проблем и способы их решения, возникающих при доступе к локальному серверу разработки в среде Android Emulator. Во время разработки фронтенда или мобильного приложения важно изменять код в локальной среде и сразу проверять результаты. Когда локальный сервер запускается с помощью такого инструмента сборки, как Vite или Webpack, адрес сервера разработки отображается в терминале, после чего этот адрес вводится в браузере для просмотра экрана.
Поскольку основным рабочим пространством во время разработки обычно является браузер на ПК, вы можете не задумываться о значении значения, введённого в адресную строку, или о направлении сетевого взаимодействия. Вы напрямую открываете терминал на компьютере, запускаете процесс сервера и подключаетесь с помощью браузера, установленного на том же компьютере, поэтому клиент и среда, на которой размещён сервер, совпадают. Однако при запуске стандартной среды AVD в Android Emulator для проверки адаптивной вёрстки на мобильном устройстве или тестирования поведения WebView вы сталкиваетесь с сетевой структурой, отличающейся от структуры браузера на ПК.
Локальный адрес, который нормально открывался в среде ПК, может не подключаться при вводе в браузере или приложении внутри эмулятора. В терминале отображаются журналы, указывающие, что сервер работает нормально, и с браузера на ПК адрес открывается без проблем, но в среде эмулятора возникает ошибка подключения. Легко предположить, что сам сервер не запущен, однако фактическая причина может заключаться в том, что сервер работает в одной среде, а запрос отправляется из другой. Для решения этой проблемы необходимо понимать назначение localhost, структуру виртуальной сети эмулятора, а также настройки привязки сервера и брандмауэра.
localhost — это имя хоста, которое обычно разрешается в loopback-адрес 127.0.0.1 в среде IPv4. Loopback-адрес возвращает сетевые запросы в сетевой стек текущего устройства, вместо того чтобы отправлять их наружу. В среде IPv6 в качестве loopback-адреса используется ::1. Иными словами, localhost не обозначает конкретное фиксированное устройство; он указывает на систему, которая в данный момент отправляет сетевой запрос. Когда вы запускаете сервер разработки в среде ПК и вводите localhost в адресную строку браузера, и клиент, и сервер находятся на ПК, поэтому запрос возвращается на сам ПК и успешно подключается.
Важно также не воспринимать localhost и адрес сервера как одно и то же понятие. localhost — это имя, обозначающее саму среду, из которой отправляется запрос, тогда как адрес и порт, на которых сервер фактически принимает запросы, являются отдельными параметрами. Например, если сервер работает на порту 5173, localhost:5173 означает, что запрос будет отправлен на порт 5173 loopback-интерфейса текущей среды. Поэтому предположение, что имя localhost всегда обозначает сервер разработки на том же компьютере, может привести к проблемам при подключении из другой среды.
При вводе localhost внутри Android Emulator ситуация меняется. Android Emulator — это виртуальное устройство Android, работающее с использованием ресурсов ПК. Когда браузер или приложение внутри эмулятора создаёт сетевой запрос, его исходной точкой является виртуальное устройство внутри эмулятора, а не ПК. Если клиент внутри эмулятора в таком состоянии отправляет запрос к localhost, сетевой стек обрабатывает его как запрос к самому эмулятору — объекту, отправляющему запрос, — а не к хост-ПК. В результате эмулятор ищет порт внутри себя, а не сервер, работающий на ПК, и не может его найти.
Для решения этой проблемы в стандартной виртуальной сетевой среде обычного Android Emulator можно использовать 10.0.2.2 как специальный адрес для доступа к loopback-интерфейсу хост-машины. Этот адрес позволяет перенаправлять запросы из эмулятора на сервер разработки хост-машины. Поэтому для доступа к серверу ПК из эмулятора замените localhost на формат с 10.0.2.2. Например, в среде, использующей порт 5173, можно отправлять запросы по адресу 10.0.2.2:5173.
10.0.2.2 по своей природе отличается от IP-адреса, назначенного ПК в обычной локальной сети. Поскольку это специальный адрес, предоставляемый для доступа к хост-ПК в виртуальной сетевой среде Android Emulator, его нельзя использовать таким же образом на физическом смартфоне. Поэтому прямое применение адреса, используемого в эмуляторе, на реальном устройстве может не сработать. Понимание этого различия позволяет отличать случаи, когда доступ в эмуляторе работает нормально, но не удаётся с физического устройства при использовании того же адреса.
Однако использование 10.0.2.2 автоматически не устраняет все проблемы с подключением. Хотя 10.0.2.2 — это адрес, предоставленный для обозначения хост-машины из эмулятора, успешность подключения также зависит от таких условий, как конфигурация привязки сервера и состояние брандмауэра. Если после правильной смены адреса подключение по-прежнему не удаётся, проверьте, настроен ли сервер на приём запросов с внешних интерфейсов.
Многие инструменты и фреймворки разработки по умолчанию настроены на привязку сервера только к интерфейсу localhost. Если сервер привязан только к 127.0.0.1, он может обрабатывать запросы через 127.0.0.1 с того же ПК, но не может принимать запросы из эмулятора, поступающие через другой сетевой интерфейс. Поэтому для доступа к серверу из среды эмулятора необходимо изменить область привязки так, чтобы сервер мог принимать запросы также через внешние интерфейсы.
В проектах, использующих Vite, конфигурацию привязки можно изменить, добавив параметр host при запуске сервера. Например, сервер можно запустить, выполнив в терминале следующую команду.
vite --host
Также его можно запустить, указав явный IP-адрес.
vite --host 0.0.0.0
Здесь 0.0.0.0 — это не адрес, обозначающий конкретное сетевое устройство. Это адрес, используемый при привязке сервера, чтобы он принимал запросы на доступных сетевых интерфейсах. Поэтому ввод 0.0.0.0 в браузере как адреса сервера имеет другое значение. Лучше понимать его как значение конфигурации, указывающее, на каких интерфейсах сервер должен принимать запросы.
Можно также изменить настройки скрипта в файле package.json проекта, используя формат npm run dev -- --host. Если сервер разработки Vite уже запущен командой npm run dev, параметр host можно применить, передав дополнительные параметры. Благодаря этой настройке можно изменить конфигурацию привязки так, чтобы сервер разработки был привязан не только к localhost, но и мог принимать запросы, поступающие через внешние сетевые интерфейсы.
Проблему привязки сервера и проблему брандмауэра операционной системы следует рассматривать как отдельные области. 10.0.2.2 решает вопрос схемы адресации, которую эмулятор использует для поиска хост-ПК, а настройка host в Vite определяет, к каким сетевым интерфейсам привязывается сервер разработки и на каких интерфейсах он принимает запросы. Брандмауэр операционной системы и настройки блокировки портов образуют отдельный уровень безопасности, который может блокировать сетевые пакеты даже после выполнения обоих этих шагов. Поэтому даже если сервер открыт для внешних запросов, подключение завершится ошибкой, если брандмауэр ПК блокирует соответствующий порт. Также следует проверить исключения брандмауэра и доступность порта.
Вместо одновременной проверки всех возможных проблем проще выявить причину, проверяя их поэтапно. Сначала используйте localhost на ПК, чтобы убедиться, что сервер работает нормально. Затем используйте 10.0.2.2 в эмуляторе, чтобы проверить, может ли он получить доступ к хост-ПК. Если доступ по-прежнему невозможен, проверьте состояние привязки сервера и, наконец, убедитесь, что брандмауэр операционной системы или защитное ПО не блокирует подключения к соответствующему порту. Поэтапное сужение области проверки упрощает определение того, связана ли проблема с самим сервером, сетью эмулятора или настройками безопасности операционной системы.
При подключении физического мобильного устройства Android вместо виртуального эмулятора для проверки экрана сетевая структура снова отличается. Физический смартфон не находится внутри виртуальной сетевой среды, используемой эмулятором, поэтому адрес 10.0.2.2 не работает. Для прямого доступа к локальному серверу ПК с физического устройства ПК и мобильное устройство должны находиться в сети, через которую они могут обращаться друг к другу. Например, если внутренний IP-адрес ПК в локальной сети — 192.168.0.10, открыть сервер в браузере или приложении смартфона можно по URL, например http://192.168.0.10:5173. В этом случае сервер также должен быть привязан для приёма запросов через внешний интерфейс, а порт не должен блокироваться брандмауэром или сетевой политикой.
При тестировании на физическом устройстве также следует помнить, что подключение ПК и смартфона к одной сети Wi-Fi не всегда гарантирует возможность обмена данными. Если маршрутизатор настроен на блокировку связи между беспроводными устройствами или если вы находитесь в корпоративной или общедоступной сети, ограничивающей доступ между клиентами, внутренний IP-адрес ПК может быть недоступен, даже когда оба устройства подключены к одной сети. Поэтому при тестировании локального сервера на физическом устройстве проверяйте не только IP-адрес и порт ПК, но и то, разрешает ли сетевая среда этим двум устройствам взаимодействовать друг с другом.
На основе рассмотренного выше можно обобщить последовательность действий по устранению неполадок, которой следует придерживаться при возникновении ошибки подключения в среде эмулятора.
Сначала откройте localhost:5173 в браузере на ПК, чтобы убедиться, что сам сервер работает нормально.
Затем в эмуляторе укажите хост-ПК, используя 10.0.2.2 вместо localhost.
Далее, если подключение по этому адресу по-прежнему не удаётся, проверьте, принимает ли сервер запросы через внешний интерфейс, и измените область привязки через конфигурацию Vite.
Наконец, если подключение по-прежнему не удаётся, хотя привязка сервера настроена правильно, проверьте, не блокируется ли порт брандмауэром операционной системы или сетевой политикой.
Следование этой последовательности и понимание структуры сети позволяют эффективно решать проблемы с подключением, возникающие при проверке мобильной среды.
При использовании локального сервера в WebView есть дополнительный фактор, который нужно проверить по сравнению с доступом из браузера. WebView также является клиентом, работающим внутри Android Emulator, поэтому при обращении к серверу на ПК localhost указывает на сам эмулятор, так же как и в браузере. Поэтому при загрузке локального сервера разработки в WebView необходимо также указать сервер разработки хост-ПК в эмуляторе в формате, например 10.0.2.2:5173. Кроме того, при выполнении приложением сетевых запросов могут потребоваться проверки других факторов в среде приложения, таких как сетевые политики Android или разрешения на доступ в Интернет. Если в браузере доступ работает нормально, а в WebView завершается ошибкой, лучше расширить область проверки за пределы адреса сервера и также проверить сетевые настройки приложения.
В средах на основе WebView локальный адрес сервера может быть указан непосредственно в коде, поэтому можно также рассмотреть возможность управления отдельными адресами для каждой среды выполнения. Например, использование адреса эмулятора в среде разработки и внутреннего IP-адреса ПК при тестировании на физическом устройстве позволит реже изменять исходный код вручную при каждом тестировании. По мере роста проекта между средами могут отличаться не только адрес сервера разработки, но и такие значения, как адрес API-сервера, поэтому удобно управлять ими с помощью переменных окружения или отдельных значений конфигурации.
Как описано выше, адрес для доступа к локальному серверу разработки может различаться в зависимости от среды разработки. Их можно различать следующим образом: localhost:5173 в браузере на ПК, 10.0.2.2:5173 в стандартном Android Emulator и внутренний IP-адрес ПК, подключённого к той же сети, при использовании физического устройства Android. Важно понимать, что эти адреса не обозначают разные серверы; это разные пути доступа для просмотра одного и того же сервера разработки из разных сред выполнения.
В конечном счёте при доступе к локальному серверу разработки важно не запомнить сам адрес, а различать среду, отправляющую запрос, и среду, в которой работает сервер. Когда браузер на ПК обращается к серверу на ПК, можно использовать localhost. Однако в Android Emulator localhost разрешается относительно эмулятора, поэтому для обращения к хост-ПК необходимо использовать 10.0.2.2. Физическое устройство Android находится в отдельной сетевой среде, поэтому нужно использовать внутренний IP-адрес, назначенный ПК. Следовательно, даже для одного сервера разработки, работающего на том же порту 5173, используемый адрес может различаться в зависимости от среды, из которой осуществляется доступ. Поняв это различие, вы сможете воспринимать ситуацию, когда localhost не работает в эмуляторе, не как простую ошибку, а как сетевую проблему, вызванную различием между источником запроса и местоположением сервера. После этого можно последовательно сужать круг возможных причин, проверяя следующие этапы, например привязку сервера и настройки брандмауэра.
KKAMJJING