Приветик. В данной статье не будет никакой занудной теории по типу «А чТо ТаКоЕ СЕРВЕР???». Мы будем вкратце описывать работу клиент-сервер, а также приведём примеры. Данная статья будет интересна тем, кто не до конца понимает как работает клиент-сервер, кто забивает в череп гвозди, чтобы повысить содержание железа и стать умнее, кто думает что клиент-сервер это что-то заоблачное для обычного начинающего кодера.
Итак, приступим к описанию принципов работы:
-
Сервер, на IP адресе {пусть это будет alpha} по порту {пусть это будет beta} ожидает подключения на указанный IP адрес {пусть это alpha2} с портом {пусть это beta2}. IP машины и IP приёма должны быть одинаковы. Порты имеют значения в диапазоне 0-65535.
-
Далее, клиент хочет зайти на ваш сервер. Изначально, наш сервер это небольшая консоль для доступа …. например к дневнику Иванова Ивана и 5Б. Клиент вводит IP {alpha2} и порт {beta2}, после чего по TCP или UPD происходит обмен данными.
-
Сервер видит что кто-то хочет посмотреть нюдсы Иванова Ивана и просто отсылает их обратно клиенту.
— Вот так мы максимально кратко расписали клиент-сервер. Распишем немного побольше…
— ЭЙ СТОЙ! А чо ещё за TCP и UPD?
— Секундочку.
Что такое UPD и TCP?
Вкратце это технологии передачи данных между двумя устройствами. Они оба разные как лолихантер и милфхантер. Приведём парочку примеров:
- Эй, Санёк, я тут камни нашёл. Можно я в тебя его кину?
- Хорошо, Шанёк, кидай
- Разрешение кидать получено!
*Кинул камни настолько мягко и последовательно, что Санёк успел словить все*
Это был пример работы TCP. Он превосходит UPD в целостности данных, строго последовательным отправлением данных и большей надёжности, но в отличии от него меньшей скоростью.
- Эй, Санёк, лови!
*Кинул камни так сильно, что Санёк сразу дал дёру, успев сначала словить большую часть камней*
- *****, не поймал, в лицо попал
Это был пример работы UPD. В отличии от своего «прилежного» брата он более быстрый в закидывании камня. Но вместо строгой последовательности отправки данных, кидает всё что видит.
Теперь черпанём немного практики.
Для начала сделаем вечно получающий информацию сервер.
Для передачи информации через сокеты в Python используем socket
import socket
Теперь же нам надо сделать слушалку.
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) IP = socket.gethostbyname(socket.gethostname()) PORT = 12333 listener.bind((IP, PORT)) listener.listen(0) connection, address = listener.accept()
socket.socket() — создаём наш сокет. Тут мы просто создаём коробку определённого вида, цвета, размера (повторяю, это формально). Но без содержимого.
socket.setsockopt() — добавляем в нашу коробку пенопласт для информации. Настраиваем опции коробки: какой пенопласт, размеры и т.д.
IP = socket.gethostbyname(socket.gethostname()) — получаем наш IP. В функцию передаётся имя ПК, IP которого мы хотим получить, в нашем случае нас.
listener.bind((IP, PORT)) — устанавливаем данные для прослушивания данного порта. Берём почтовый ящик IP/PORT. Данные передаются кортежем, это не ошибка!
listener.listen() — разрешаем серверу принимать запросы.
listener.accept() — в случае найденного пользователя разрешаем ему подключиться
Теперь у нас есть почтовый ящик и заранее готовая коробка с посылкой. Теперь нам нужно проверять наш почтовый ящик. Наш почтовый ящик вмещает 1 КБ (1024 байт). Поэтому нам нужно каждый раз открывать ящик, забирать оттуда данные и продолжать до тех пор, пока ящик не опустеет.
connection.send("Привет, подкючайся!".encode('utf8')) connection.send("Привет!".encode('utf8')) while True: data_output = '' while True: data = connection.recv(1024).decode("utf8") data_output+=data if not data: break print(data_output)
connection.send() — отправить данные. Для вашей же живучести используйте .encode(«utf8»)
connection.recv(1024) — получить 1024 байт данных. Для вашей же живучести используйте .decode(«utf8»)
Вот так мы будем получать информацию о том, что нам отправили. Это как будто вы перевернули почтовый ящик вверх дном и высыпаете оттуда всё до конца.
— Но зачем в начале нам отправлять данные?
Таким образом мы показываем клиенту что готовы работать. Если бы мы этого не сделали, клиент бы стоял молчал.
Раз уж с сервером окончено перейдём к клиенту
import socket connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) IP = "айпи сервера" PORT = 12333 connection.connect((IP, PORT)) rd = connection.recv(1024) print(rd.decode('utf8')) connection.send("И тебе привет!".encode('utf8')) connection.close()
connection.connect() — начать подключение. Данные в функцию передаются кортежем!
connection.close() — закрыть соединение
Ну вот, теперь при запуске клиента по IP, от сервера мы получим «Привет», а сервер получит наше «И тебе привет!», а также продолжит ждать от нас ответ.
Прошу акцентировать внимание, что эти каналы легко прослушать, а по сему для передачи личных данных желательно пользоваться алгоритмами шифрования (например идеально подойдёт RSA).
Немного дополнительных вопросов:
-
Можно ли при помощи сокетов сделать консоль? Как реализовать в нём команды?
-
Конечно. Команды можно реализовать просто отправкой сообщения, а после получения обработкой через условия.
-
Как сделать таймаут?
-
Используйте на вашем подключении .settimeout(Время в секундах).
-
Что если я укажу чужой адрес в прослушивании сервера?
-
Вам просто выбьет ошибку.
-
Можно ли по сокетам передавать фото, видео и т.д.?
-
Да, конечно. Фото и видео это просто данные. Их можно прочесть, а соответственно и отправить.
Небольшая справочка по основным командам для создания сокетов:
socket.socket(socket.AF_INET, socket.SOCK_STREAM) — создать сокет
socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) — настроить сокет
socket.gethostbyname(socket.gethostname()) — получить наш готовый IP
listener.bind((IP, PORT)) — прослушивать данный IP по порту. Данные передаются кортежем!
listener.listen(0) — разрешаем серверу принимать запросы
listener.accept() — принимаем запрос на передачу данных
connection.send() — отправить данные
connection.recv(1024) — получить данные. Значение в скобочках, количество байт которые можно принять за один раз
connection.settimeout() — установить таймаут соединения
connection.connect() — установить подключение к серверу
connection.close() — закрыть соединение
Дополнительные источники, полезные ссылки:
И на этом мы закончим вступление клиент-сервер в Python для зародышей. Напомню что данная статья не создана для Truehard кодеров, она создана для тех кто не разбирается в сокетах и хочет понять как с ними работать.
ссылка на оригинал статьи https://habr.com/ru/articles/580710/
Добавить комментарий