Делаем свой клиент DMconnect.
Добро пожаловать на сайт! Здесь вы сможете узнать о том, как же всё-таки сделать свой собственный, идеальный (для вас) клиент, работающий по протоколу DMconnect. Но обо всём по порядку. Скажу сразу, клиент будет писаться на ЯП Python 3. Кто огорчится, кто обрадуется. Собственно, большинство клиентов DMconnect (в том числе и официальный) основаны именно на этом ЯП, так что чего-то сильно неизведанного тут нет. Вам же никто не мешает просто взять код какого-то клиента, изменить гамму, добавить кучу полезных (вам) функций и "готово" :-).
Про сам DMconnect.
С этого, я думаю, стоит начать. Если вы уже с самим DMconnect'ом ознакомлены - смело пролистывайте этот раздел, он вам не пригодится. DMconnect - протокол обмена сообщениями в реальном времени, созданный совсем недавно (на момент создания сайта, разумеется) - в конце сентября 2024. DMconnect можно легко сравнить с IRC, хоть это обычного и не делают: там есть те же каналы (на "жаргоне" DMconnect-а - сервера / подсервера), пользователи на канале (подсервере) и всё прочее присущее протоколу IRC. Тем не менее, имеются различия, которые на первый взгляд не видны. Самое главное, наверное, это невозможность войти на несколько подсерверов одновременно, как это реализовано в IRC, а также полное отсутствие возможностей получить информацию о каком-то пользователе не используя консоль или саму файловую систему сервера. Подсервер вы должны выбрать при входе (уже после авторизации, разумеется), нет подсервера - нет общения. С этим, думаю, разобрались, можем смело переходить далее.
Главный плюс DMconnect.
Тут всё по аналогии с предудыщим разделом - знаете, значит пропускаете. Несомненно, главным плюсом DMconnect'a перед другими протоколами служит его "исходность", т. е. вы можете натурально отправить серверу сообщение вида /login test password, закодированное в UTF-8 и сервер вам ответит в том же "исходном" виде, например, "Login sucessful". Думаю, теперь новичкам протокол будет казаться не таким уж и страшным :-).
Приступим!
А вот этот раздел попрошу не пропускать, здесь мы уже начнём освоение протокола. Для тех, кто хочет более детально со всем ознакомится, существует документация по протоколу, но новичкам она не так уж полезна. Для начала, определимся с командами. В DMconnect существует всего несколько команд, список представлен ниже, описания - из официального /help:
/login <пользователь> <пароль> - Войти с вашим именем пользователя и паролем.
/register <пользователь> <пароль> - Зарегистрировать новый аккаунт.
/create_server <имя_сервера> - Создать новый сервер для общения.
/join_server <имя_сервера> - Войти на существующий сервер.
/list_servers Получить список всех доступных серверов.
/members Получить список пользователей на сервере.
/pm <пользователь> <сообщение> - Отправить личное сообщение пользователю.
/act <параметр> - чат-экшен.
/help - ну вы поняли :-)
Но перед тем, как использовать всё это добро, очевидно, нужно подключиться к серверу. Как это сделать? Всё до ужаса просто:
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("147.185.221.19", 42439))
Собственно, всё подключение. Обратите внимание, что адрес сервера (тьфу, тьфу) может измениться, информация об актуальном адресе скорее всего будет доступна на сайте DMconnect или на сайте его текущего владельца. Теперь организуем сам приём сообщений. Для этого, добавьте в начало вашего кода строки:
import threading
stop_event = threading.Event()
То есть, наш код будет выглядеть примерно так:
import socket
import threading
import re
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("147.185.221.19", 42439))
stop_event = threading.Event()
И сразу к вопросу, что же здесь делает переменная stop_event? Это - отражение статуса работы программы. При выполнении она всегда будет равна True, пока мы не совершим "аварийное" отключение от сервера (например, нажав CTRL+C). Конечно, сервер и сам отключает неактивных сокетов (клиентов) от себя, но это происходит с некоторой задержкой (в среднем - 1-2 минуты). Можно переходить к полноценному механизму общения с сервером, делаем функцию receive_messages:
def receive_messages():
while not stop_event.is_set():
message = client_socket.recv(1024).decode('utf-8').strip() # decode и strip ОБЯЗАТЕЛЬНЫ! Системные сообщения в основном приходят с лишними символами, по типу \n.
if not message:
break
print(message)
И добавляем вызов функции, прописав receive_messages(). Если подключение прошло успешно, мы увидем заветные сообщения от сервера:
Enter command (/login /register):
Сервер ждёт ввода нашей команды: для авторизации или для регистрации. Теперь пришло время вынести функцию приёма сообщений в другой поток, дабы мы могли одновременно как вводить, так и получать сообщения. Добавим функцию start_receiving_thread:
def start_receiving_thread():
receive_thread = threading.Thread(target=receive_messages, daemon=True)
receive_thread.start()
Обычный вызов receive_messages нужно убрать, заменив его вызовом start_receiving_thread(). Если запустить текущий код, то ничего не произойдёт. Дело в том, что нам требуется добавить какой-то цикл, который бы выполнялся бесконечно (while True). Напишем что-то вроде:
while True:
pass
Это буквально цикл, который ничего не делает. Можете поэкспериментировать, добавьте туда, например, бесконечный print("Hello World") с задержкой в 1 минуту, сообщения из сервера DMconnect всё равно продолжат приниматься с должной (мгновенной) скоростью - в этом и есть весь смысл "поточности" нашего клиента. Теперь пора заняться не менее важной по сравнению с приёмом сообщений функцией - отправкой. Всё предельно просто, заменяем наш "пустой" цикл следующим кодом:
while True:
msg = input()
client_socket.send(msg.encode('utf-8'))
Обратите внимание, что и отправляемые сообщения кодируются в принятую за стандарт кодировку UTF-8. Запускаем и... клиент работает! Можно делать абсолютно всё, что только душе угодно. Проходим авторизацию, заходим на подсервер и общаемся :-). В результате наш код будет выглядеть так:
import socket
import threading
import re
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("localhost", 1111))
stop_event = threading.Event()
def receive_messages():
while not stop_event.is_set():
message = client_socket.recv(1024).decode('utf-8').strip()
if not message:
break
print(message)
def start_receiving_thread():
receive_thread = threading.Thread(target=receive_messages, daemon=True)
receive_thread.start()
start_receiving_thread()
while True:
msg = input()
client_socket.send(msg.encode('utf-8'))
Клиент получился всего на 26 строк! Разумеется, представленный код - лишь макет, выпускать такой "голый" клиент общественности, а уж тем более пользоваться им заместо имеющихся альтернатив - нецелесообразно. Надеюсь, инструкция ответила на все ваши вопросы касаемо протокола, подключения, отправки сообщений и т. д.
Спасибо за внимание!