#java #android #sockets #adb #serversocket
#java #Android #сокеты #adb #serversocket
Вопрос:
Ситуация: телефон Android был подключен к ПК через USB. Используя команду ADB adb forward tcp:35000 tcp:30000
, мне удается перенаправить порт.
Я хочу, чтобы компьютер отправлял свое системное время на телефон Android каждые 5 секунд в течение часа. С этой целью я выполняю программирование сокетов.
Сторона ПК в качестве клиента: (Я игнорирую код обработки исключений.)
public void sendTime()
{
class SendTask implements Runnable
{
public void run()
{
// Here: I store the host_socket in a member field which is:
// Socket host_socket = new Socket("localhost", 35000);
ObjectOutputStream oos = new ObjectOutputStream(this.host_socket.getOutputStream());
oos.writeObject(msg);
oos.flush();
}
}
// Here: private Executor exec = Executors.newCachedThreadPool();
this.exec.execute(new SendTask());
}
Телефонная сторона Android в качестве сервера:
public void getReadyForSync()
{
ServerSocket server_socket = new ServerSocket();
server_socket.bind(new InetSocketAddress("localhost", 30000));
while (true)
{
final Socket client_socket = server_socket.accept();
Runnable receive_task = new Runnable()
{
public void run()
{
ObjectInputStream ois = new ObjectInputStream(client_socket.getInputStream());
Message msg = (Message) ois.readObject();
SyncTimeFragment.this.onReceive(msg);
}
};
// Here: private static final Executor exec = Executors.newCachedThreadPool();
exec.execute(receive_task);
}
}
Кроме того, ServerSocket устанавливается в отдельном потоке от основного потока Android с использованием AsyncTask
и new ServerTask().execute()
:
public class ServerTask extends AsyncTask<String, Void, Void>
{
protected Void doInBackground(String... params)
{
getReadyForSync();
return null;
}
}
Проблемы:
В моем тесте серверный сокет в телефоне Android принимает соединения с ПК только один раз.
В частности, некоторая отладочная информация выглядит следующим образом:
(1) При каждом вызове (каждые 5 секунд) sendTime()
выполняется host_socket
чтение:
Socket[addr=localhost/127.0.0.1,port=35000,localport=56520]
Обратите внимание: значения localport
(ы) здесь одинаковы для всех sendTime()
вызовов в одном выполнении, но различаются в разных исполнениях. (Я не уверен, важна ли эта информация или нет.)
(2) server_socket
Чтения:
Socket[addr=localhost/127.0.0.1,port=0,localport=30000]
(3) client_socket
Полученные (только один раз) server_socket
чтения:
Socket[addr=/127.0.0.1,port=43890,localport=30000]
Комментарии:
1. Нет. Сервер может принимать много клиентов. Но если у вас только один клиент…
2. @greenapps Однако единственный клиент вызывал этот
sendTime()
метод много раз (каждые 5 секунд в течение часа). Другими словами, было выпущено много соединений с ПК, но только одно (первое) из них было принято сервером. Есть идеи?3. Нет. Подключений не так много. Это не то же самое соединение. Вы не закрываете и не переподключаетесь для каждого вызова. Если бы вы затем поместили это в свой код, пожалуйста. Как и сейчас,
//new Socket
неясно, что происходит.4. @greenapps Извините, я не совсем хорошо понимаю. Вы имеете в виду, что я каждый раз использую одно и то же соединение
host_socket: Socket[addr=localhost/127.0.0.1,port=35000,localport=56520]
? Означает ли это, что я не могу отправлять разные сообщения, повторно используя соединение?5. @greenapps Следуя вашим инструкциям, я исправил ошибку: создайте новый сокет в методе
sendTime()
вместо сохраненияhost_socket
в качестве поля-члена и повторного его использования. Спасибо. Однако я не совсем понимаю, почему мы не можем повторно использовать соединение. Не могли бы вы дать некоторое объяснение в ответе. Я приму это.
Ответ №1:
После создания receive_task
кода возвращается к final Socket client_socket = server_socket.accept();
So, сервер отбрасывает соединение, так как run()
получает только одно сообщение. Вам тоже пришлось бы сделать while
цикл run()
.
Комментарии:
1. В комментариях после сообщения я исправил ошибку «плохим» способом: каждый раз создавайте новый сокет в методе
sendTime()
вместо сохраненияhost_socket
в качестве поля-члена и повторного его использования. Это может вызвать проблемы с производительностью. @TassosBassoukos2. Это также может привести к утечке ресурсов; предотвратите это, просто выполнив цикл в receive_task; не забудьте поместить все в try-finally, чтобы освободить сокеты…