Socket

Java Collections
10 уровень , 7 лекция
Открыта

— Привет, Амиго!

— Здорово, Риша!

— Тема сегодняшней лекции – Сокеты. Socket в переводе с английского – Розетка.

Ты уже знаешь, что у каждого компьютера в сети есть его уникальный IP-адрес.

— Ага.

— И вот представь, что у тебя есть несколько компьютеров и на каждом компьютере запущено с десяток программ, которые работают с интернетом: Skype, ICQ, и т.д.

И эти программы хотят общаться между собой.

Надо сделать так, чтобы они друг другу «не мешали». Чтобы Skype связывался со Skype’ом, ICQ с ICQ и т.д.

Помнишь, как это проблему решили с URL и веб-серверами?

— Ага, добавили порты.

— Именно.

Это все равно, что в доме сделать много маленьких комнат и объявить его многоквартирным. Каждый порт – это как отдельная квартира.

Так вот IP-адрес – это уникальный номер компьютера, а IP-адрес+порт – это уникальный номер некой «квартиры» (ячейки) в компьютере, которую может занять программа.

Вот такая уникальная ячейка и называется сокет.

У сокета есть его уникальный номер, и состоит он из IP-адреса и номера порта.

— Ага. Т.е. сокет – это номер некой виртуальной ячейки в компьютере, которую может занимать программа? А другая программа будет слать ей в эту ячейку сообщения, и таким образом они будут общаться?

— Не знаю, как ты это понял, но именно так и есть.

— Это моя робоинтуиция подсказала.

— Отлично. Тогда давай немного подробностей.

Сокеты – это фактически самый базовый и самый примитивный способ межсетевого взаимодействия программ.

В Java для работы с сокетами есть два класса. Это классы Socket и ServerSocket.

ServerSocket – это специальный класс, объекты которого выполняют роль сервера – т.е. могу обслуживать запросы, пришедшие на определенный сокет.

Класс Socket – это фактически Socket-клиент, с помощью него мы можем послать сообщение некоторому сокету и получить ответ.

Как послать сообщение какому-то сокету:

Пример
//создаем сокет
Socket clientSocket = new Socket("localhost", 4444);

//получаем OutputStream
OutputStream outputStream = clientSocket.getOutputStream();
PrintWriter out = new PrintWriter(outputStream, true);
out.println("Kiss my shiny metal ass!");
out.flush();

//читаем ответ
InputStream inputStream = clientSocket.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
String answer = in.readLine();

— Все очень напоминает скачивание файла из интернета.

— Это потому, детка, что там тоже используются сокеты.

Сокеты используются в основе всего связанного с сетью, ну или почти всего.

Вот тут можешь почитать дополнительную информацию.

— Спасибо за лекцию, Риша.

— Это еще не все. Размечтался.

Теперь мы разберемся, как работает серверный сокет.

Он работает чуток посложнее.

Пример
//создаем объект сервер-сокет
ServerSocket serverSocket = new ServerSocket(4444); //порт

//в цикле обрабатываем входящие соединения.
while (true)
{
 //метод accept ждет, пока кто-то не подключится.
 Socket socket = serverSocket.accept();

 //читаем сообщение
 InputStream inputStream = socket.getInputStream();
 BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
 String message = in.readLine();

 //придумываем ответ – просто разворачиваем строку задом наперед
 String reverseMessage = new StringBuilder(message).reverse().toString();

 //отправляем ответ
 OutputStream outputStream = socket.getOutputStream();
 PrintWriter out = new PrintWriter(outputStream, true);
 out.println(reverseMessage);
 out.flush();
}

Хочу обратить твое внимание на несколько моментов.

Момент 1: Для создания сокета нужно указывать IP-адрес (или домен) и порт. Для создания серверного сокета – только порт. Серверный сокет появляется только на том компьютере, где его создали.

Момент 2: У класса ServerSocket есть метод accept(), который, если его вызвать, будет ждать входящее соединение. Т.е. метод будет выполняться бесконечно долго, пока какой-то клиентский сокет не попробует обратиться к нему. Тогда метод accept() примет соединение, создаст объект сокет для коммуникации и после этого вернет этот объект.

С точки зрения Java-программиста, сокет – это два потока – InputStream из которого можно читать сообщения/данные и OutputStream, куда можно писать сообщения/данные.

Когда ты создаешь серверный сокет, фактически появляется порт, к которому могут подключаться сокеты с других компьютеров. Но для этого им надо правильно указать номер порта нашего сокета и IP-адрес нашего компьютера. Ну, или его доменное имя.

Вот тебе интересный пример, можешь попробовать разобрать его и выполнить:

http://habrahabr.ru/post/69136/

Там весь смысл в том, что с помощью серверного сокета пишется примитивнейший веб-сервер, к которому можно просто обращаться из браузера.

— Ого! Веб-сервер? Круто! Я изучу его очень внимательно.

Спасибо, Риша.

— Все, Амиго, иди отдыхать!

Комментарии (28)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Denis Odesskiy Уровень 47
18 июня 2025
На Java можно использовать пакет NIO и очень эффективно реализовать асинхронный сокет-сервер, так сказать по образу и подобию из статьи на хабре который... А еще можно использовать Spring Boot + Spring WebFlux и ничего не реализовывать😄.
Artem Уровень 47
26 мая 2024
ChatBot -> Servlets -> HttpClient -> Java mail api -> socket
И. Ж. Уровень 41
29 марта 2024
Как раз задача по написанию чата была
Igor Petrashevsky Уровень 47
30 августа 2022
:facepalm: а вот и снова сокетами поводили по губам
LuneFox Уровень 41 Expert
31 марта 2022
Смог обмануть клиент приложения OwnCloud (облачное хранилище), подсунув ему из сокета ответ, который он хочет слышать от настоящего сервера. Узнал я его, попытавшись подключиться к серверу из примера и выведя запрос на экран, а затем выполнив его из браузера (GET /status.php). Он даже не ругнулся, а предложил продолжить вход. При нажатии на Click here сокет получил дальнейший запрос:

GET /index.php/settings/personal?sectionid=security HTTP/1.1
Host: localhost:8082
Теперь я хотя бы примерно представляю, как это работает :) То есть, чтобы создать с нуля свой сервер, нужно читать заголовки запросов и реагировать на них определённым образом, а неизвестные запросы отклонять.
Igor Petrashevsky Уровень 47
30 августа 2022
http, ftp, snmp, pop3, smtp - это все надстройки над древнейшим протоколом telnet , который появился до tcp/ip и умел только в текст. Сделаете telnet - сделаете все остальное, путем добавки/смены костылей. Это полезно в учебных целях, т.к. для практики есть готовые фрэймворки со всеми необходимыми велосипедами.
Fomka_Wyverno Уровень 41
27 ноября 2021
Отсылка на Бэндера? out.println("Kiss my shiny metal ass!");
Ars Уровень 41
5 декабря 2021
Тут весь курс - отсылка на Футураму. А точнее раньше все персонажи были оттуда. Но потом переделали.
Valua Sinicyn Уровень 41
4 марта 2021
Сокеты на человеческом.
Женя Уровень 41
23 февраля 2021
"— Не знаю, как ты это понял, но именно так и есть". Наверно, если бы у валидатора было сознание, он бы то же самое после успешной валидации сообщал.
Alexey Prilessky Уровень 40
15 декабря 2020
Интересно про это читать, когда уже в Multithreading Написали свой онлайн чат )
Roman Уровень 41
22 февраля 2021
То чувство, когда сначала пошел в коллекции 😎
ZюMLik Уровень 51
5 августа 2023
и там с этим разбираешься сам )
Konstantin Уровень 41
28 сентября 2020
"http://habrahabr.ru/post/69136/" - шёл 2020 год