У меня экстремальные потери пакетов UDP с Android, и это не имеет смысла. Ситуация следующая:
- ПК с Java-клиентом, подключенным к домашней сети
- Телефон с Java-сервером (Android), подключенным к домашней сети
- Домашний роутер — новый WRT1900ac. Сеть имеет выход в интернет.
- Пакеты UDP маленькие (‹ 15 байт)
Симптомы:
Если ПК отправляет пакет UDP на другой ПК (оба в одной сети), он работает очень хорошо (пакеты почти не теряются).
Если Android отправляет пакет UDP на ПК в той же сети, он также работает очень хорошо (пакеты почти не теряются).
Если ПК отправляет UDP на Android в той же сети, я получаю большие потери пакетов (50% времени или более, но это бывает по-разному).
В большинстве случаев я вынужден отправить пакет около 10 раз, чтобы пройти один. В остальное время все проходит с довольно большой задержкой. Очень странное поведение, которое происходит только на принимающей стороне Android. Если я заменю android на компьютер с тем же кодом на java или просто получу пакет через UDP-сервер Packet Sender, у меня не будет проблем с потерей. Еще одна вещь, которую я заметил, заключается в том, что если вместо использования маршрутизатора я использую другую точку доступа, которая не имеет подключения к Интернету или других клиентов, производительность резко улучшается. Это ожидаемо, но мой вопрос заключается в том, почему принимающая сторона Android наблюдает такую плохую производительность и теряет так много пакетов. Когда Android заменяется другим ПК с тем же кодом и в той же сети, проблем не возникает. Android
также не имеет проблем с отправкой пакетов (пакеты не теряются). Следовательно, это должно быть что-то еще, связанное с Android на принимающей стороне...
Я также попытался заменить код ПК на Packet Sender и получил те же результаты. Проблема, похоже, в принимающей стороне Android. Я запускаю один и тот же код UDP на стороне ПК и на Android.
Код отправки UDP прост:
public void sendMessage(String message)
{
try {
DatagramSocket ds = new DatagramSocket();
DatagramPacket dp;
InetAddress local = InetAddress.getByName(ipPool);
dp = new DatagramPacket(message.getBytes(), message.length(), local, port);
ds.setBroadcast(true);
ds.send(dp);
ds.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Код получения UDP на Android находится в классе сервера UDP:
public class UDP_Server
{
CommandParser commandParser;
public UDP_Server(MainActivity mainActivity)
{
Log.i("Udp tutorial", "---------------------------Starting UDP SERVER");
commandParser = new CommandParser(mainActivity);
String text;
int server_port = 9876;
try
{
DatagramSocket s = new DatagramSocket(server_port);
s.setBroadcast(true);
//s.setReceiveBufferSize(163840);
while (true)
{
byte[] message = new byte[1024];
DatagramPacket p = new DatagramPacket(message, message.length);
s.receive(p);
text = new String(message, 0, p.getLength());
Log.d("Udp tutorial","message:" + text);
//commandParser.parseCommand(text);
//s.close();
}
} catch (SocketException e)
{
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Класс UDPServer.java создается с помощью метода основного действия onCreate():
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
wm = (WifiManager) getSystemService(WIFI_SERVICE);
Log.i("Udp tutorial", "---------------------------HERE 1");
Thread thread = new Thread(new Runnable()
{
public void run()
{
UDP_Server svr = new UDP_Server(MainActivity.this);
}
});
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
// TCPServer server = new TCPServer();
}