Я делаю приложение чата для Android и в настоящее время тестирую с 2 эмуляторами и телефоном, подключенным через USB.
Я не смог получить Socket для подключения к ServerSocket в течение последних 24 часов. Каждый хост использует ServerSocket для прослушивания разговоров других хостов через их клиентские сокеты.
Для обоих эмуляторов выводятся следующие 2 строки кода:
The server socket is using ip: /::
serverSocket = new ServerSocket(portNo);
Log.i("MY_TAG", "The server socket is using ip: " + serverSocket.getInetAddress() );
Используя следующую строку кода, я получаю исключение ConnectionException, в котором говорится, что оно не может подключиться к указанному IP-адресу и порту и что время подключения истекло:
socket = new Socket(addr, portNo);
Я получаю IP-адрес, запрашивая сервер каждые 20 секунд, а в сценарии php я использую $_SERVER['REMOTE_ADDR']
который действительно возвращает мой IP-адрес.
При использовании телефона для отправки сообщения в эмулятор я получаю немного другую ошибку. Я получаю исключение ConnectionException, как и в случае с эмуляторами, за исключением того, что в нем также указано «Соединение отклонено».
При отправке сообщения с эмулятора на телефон я получаю исключение ConnectionException из-за истечения времени ожидания.
ServerSocket телефона использует ip 0.0.0.0, что, я знаю, хорошо, потому что это означает, что он просто прослушивает все интерфейсы.
Во всех случаях метод accept () Server Socket никогда не возвращается.
С помощью netstat -an
(Я использую Windows в качестве своей ОС), я не увидел ни одного из портов, которые якобы прослушивал мои ServerSockets, перечисленных в выводе.
Используя telnet, я получаю сообщение об отказе в соединении при попытке на эмуляторе (используя php $_SERVER['REMOTE_ADDR']
чтобы получить IP).
И я получаю тайм-аут соединения при использовании telnet на ip и порту прослушивания телефона.
Тем не менее, пожалуйста, помогите мне выяснить, как подключить эти разъемы.
Простой ответ — то, что я пытался сделать, невозможно (по крайней мере, не прыгая через некоторые обручи). Проблема в том, что оба хоста находятся за маршрутизаторами NAT.
Маршрутизаторы NAT работают так, что когда им поступает входящее сообщение, они смотрят номер порта в сообщении и затем переводят его во внутренний ip и номер порта, соответствующий какому-либо узлу, сидящему в локальной сети, скрывающемуся за ним. Это делается с помощью так называемой таблицы трансляции NAT. Проблема с моим дизайном заключается в том, что для входящих сообщений из мира в NAT, я передаю NAT номер внутреннего порта, когда мне действительно нужно кормить его любым номером порта, который NAT назначил внутреннему порту хоста при отправке сообщения ,
Вот картинка, чтобы описать то, что я говорю (взято из слайдов лекции Алекса С. Сноерена, замечательного профессора по сетевым технологиям в UCSD):
Мое решение будет состоять в том, чтобы перепроектировать то, что я делаю, с помощью единственного ServerSocket, постоянно прослушивающего новые соединения на каком-то веб-хосте.
Других решений пока нет …