Socket

Открыта

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

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

— Тема сегодняшней лекции – Сокеты. 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 Full Stack Developer
18 июня 2025, 22:35
На Java можно использовать пакет NIO и очень эффективно реализовать асинхронный сокет-сервер, так сказать по образу и подобию из статьи на хабре который... А еще можно использовать Spring Boot + Spring WebFlux и ничего не реализовывать😄.
Artem
Уровень 47
26 мая 2024, 19:40
ChatBot -> Servlets -> HttpClient -> Java mail api -> socket
И. Ж.
Уровень 41
29 марта 2024, 12:55
Как раз задача по написанию чата была
Igor Petrashevsky
Уровень 47
30 августа 2022, 22:44
:facepalm: а вот и снова сокетами поводили по губам
LuneFoxJava Developer в BIFITExpert
31 марта 2022, 21:32
Смог обмануть клиент приложения OwnCloud (облачное хранилище), подсунув ему из сокета ответ, который он хочет слышать от настоящего сервера. Узнал я его, попытавшись подключиться к серверу из примера и выведя запрос на экран, а затем выполнив его из браузера (GET /status.php). Он даже не ругнулся, а предложил продолжить вход. При нажатии на Click here сокет получил дальнейший запрос:
GET /index.php/settings/personal?sectionid=security HTTP/1.1
Host: localhost:8082
Теперь я хотя бы примерно представляю, как это работает :) То есть, чтобы создать с нуля свой сервер, нужно читать заголовки запросов и реагировать на них определённым образом, а неизвестные запросы отклонять.
Igor Petrashevsky
Уровень 47
30 августа 2022, 22:47
http, ftp, snmp, pop3, smtp - это все надстройки над древнейшим протоколом telnet , который появился до tcp/ip и умел только в текст. Сделаете telnet - сделаете все остальное, путем добавки/смены костылей. Это полезно в учебных целях, т.к. для практики есть готовые фрэймворки со всеми необходимыми велосипедами.
Fomka_Wyverno
Уровень 41
27 ноября 2021, 19:14
Отсылка на Бэндера? out.println("Kiss my shiny metal ass!");
Ars
Уровень 41
5 декабря 2021, 10:19
Тут весь курс - отсылка на Футураму. А точнее раньше все персонажи были оттуда. Но потом переделали.
Valua Sinicyn
Уровень 41
4 марта 2021, 10:32
Сокеты на человеческом.
Женя
Уровень 41
23 февраля 2021, 07:59
"— Не знаю, как ты это понял, но именно так и есть". Наверно, если бы у валидатора было сознание, он бы то же самое после успешной валидации сообщал.
Alexey Prilessky
Уровень 40
15 декабря 2020, 16:44
Интересно про это читать, когда уже в Multithreading Написали свой онлайн чат )
RomanBackend Developer в Yandex
22 февраля 2021, 10:12
То чувство, когда сначала пошел в коллекции 😎
ZюMLik
Уровень 51
5 августа 2023, 07:34
и там с этим разбираешься сам )
Konstantin
Уровень 41
28 сентября 2020, 07:11
"http://habrahabr.ru/post/69136/" - шёл 2020 год