Неужели все происходит через передачу текстовой информации методом InputStream getInputStream и т.д.
Да, примерно так и есть, только не текстовой, а бинарной, как правило. Другое дело, что во-первых, это всё оборачивается кучей слоёв абстракций, чтобы было удобней с этим работать. Во-вторых, getInputStream - это для синхронного вводе-вывода, есть ещё асинхронный, там всё несколько сложнее.
Для решения различных задач клиент-серверного взаимодействия существует немало библиотек и фреймворков. Я рекомендую вам посмотреть в сторону
netty, попробовать tutorail-ы и т.п., чтобы понять как оно работает.