Простой мессенджер на tkinter,socket и threading

В этой статье я бы хотел показать как написать простое приложение мессенджер менее чем в 150 строк.
Серверная часть
Начнём с сервера(наше приложение будет состоять из скриптов сервера и клиента), через который можно получать входящие запросы от клиентов, желающих общаться. Традиционно указываем путь до интерпретатора и импортируем необходимые модули. Конкретно socket и threading. Первый отвечает непосредственно за “общение” процесссов между собой, второй за многопоточность. О этих модулях подробно можно почитать например здесь — socket , threading.
Использование фреймворков, таких как Twisted и SocketServer, было возможным, но мне показалось это излишним для такого простого программного обеспечения, как наше.
Давайте обозначим константы, отвечающие например за адрес порта и размер буфера.
Теперь мы разбиваем нашу задачу на прием новых соединений, рассылку сообщений и обработку определенных клиентов. Давайте начнем с принятия соединений:
Это просто цикл, который всегда ждет входящих соединений и, как только он его получает, регистрирует соединение (печатает некоторые сведения о соединении) и отправляет подключенному клиенту приветствие. Затем он сохраняет адрес клиента и позже запускает поток обработки для этого клиента. Конечно, мы еще не определили для этого целевую функцию handle_client (), но вот как мы это сделаем:
Естественно, после того, как мы отправим новому клиенту приветственное сообщение, он ответит именем, которое он хочет использовать для дальнейшего общения. В функции handle_client () первая задача, которую мы делаем, — мы сохраняем это имя, а затем отправляем клиенту еще одно сообщение о дальнейших инструкциях. После этого идет основной цикл: здесь мы получаем дополнительные сообщения от клиента и, если сообщение не содержит инструкций для выхода, мы просто передаем сообщение другим подключенным клиентам (мы определим метод широковещания через минуту ). Если мы сталкиваемся с сообщением с инструкциями выхода (то есть клиент отправляет ), мы возвращаем то же самое сообщение клиенту, а затем мы закрываем сокет подключения для него. Затем мы делаем очистку, удаляя запись для клиента, и, наконец, сообщаем другим связанным людям, что этот конкретный человек покинул чат.
Теперь пропишем функцию broadcast ():
Эта функция просто отправляет сообщение всем подключенным клиентам и при необходимости добавляет дополнительный префикс. Мы передаем префикс для broadcast () в нашей функции handle_client () и делаем это так, чтобы люди могли точно знать, кто является отправителем конкретного сообщения. Это были все необходимые функции для нашего сервера. Наконец, мы добавили код для запуска нашего сервера и прослушивания входящих соединений:
Мы присоединяемся к ACCEPT_THREAD, чтобы основной скрипт ожидал его завершения и не переходил на следующую строку, которая закрывает сервер. Это завершает наш серверный скрипт.
В итоге получаем вот такой код для серверной части:
Клиентская часть###
Теперь приступим к наиболее интересной части нашего приложения — к клиенту. В качестве gui будем использовать tkinter, т.к в нём довольно легко построить несложное приложение. Традиционно импортируем модуль tkinter, а также модули использовавшиеся ранее при написании серверной части программы.
Теперь мы напишем функции для обработки отправки и получения сообщений. Начнем с получения:
Почему мы снова используем бесконечный цикл? Потому что мы будем получать сообщения совершенно независимо от того, как и когда мы отправляем сообщения. Мы не хотим, чтобы это было приложение для чата с функциональностью уровня рации. Мы хотим приложение в котором можно отправлять или получать сообщения одновременно; мы хотим получать сообщения, когда сами того пожелаем, и отправлять их, когда захотим.
Функциональность внутри цикла довольно проста; recv () является блокирующей частью. Он останавливает выполнение до тех пор, пока не получит сообщение, а когда это произойдет, мы продвигаемся вперед и добавляем сообщение в msglist. Затем мы определяем msg_list, который является функцией Tkinter для отображения списка сообщений на экране. Далее мы определим функцию send ():
my_msg — это поле ввода в графическом интерфейсе, и поэтому мы извлекаем сообщение для отправки с помощью msg = my_msg.get (). После этого мы очищаем поле ввода и затем отправляем сообщение на сервер, который, как мы видели ранее, передает это сообщение всем клиентам (если это не сообщение о выходе). Если это сообщение о выходе, мы закрываем сокет, а затем приложение с графическим интерфейсом (через top.close ())
Мы определяем еще одну функцию, которая будет вызываться, когда мы решим закрыть окно с GUI. Это своего рода функция очистки до закрытия, которая закрывает соединение с сокетом до закрытия графического интерфейса:
Это устанавливает в поле ввода значение , а затем вызывает send (). Начнем с определения виджета верхнего уровня и установки его заголовка, как и в любой другой программе на tkinter:
Затем создаём фрейм со списком сообщений, поле для ввода сообщений и скроллбар для перемещения по истории переписки
“Упаковываем” наши элементы и размечаем их расположение в окне:
После этого мы создаем поле ввода для пользователя, чтобы ввести свое сообщение, и привязать его к строковой переменной, определенной выше. Мы также привязываем его к функции send (), чтобы всякий раз, когда пользователь нажимает return, сообщение отправлялось на сервер.
Далее мы создаем кнопку отправки, если пользователь желает отправить свои сообщения, нажав на нее. Опять же, мы связываем нажатие этой кнопки с функцией send ().
И да, мы также упаковываем все то, что создали только сейчас. Кроме того, не забудьте использовать функцию очистки on_closing (), которая должна вызываться, когда пользователь хочет закрыть окно GUI:
И вот мы подходим к завершению. Мы еще не написали код для подключения к серверу. Для этого мы должны запросить у пользователя адрес сервера. Я сделал это, просто используя input (), чтобы пользователь встретился с подсказкой командной строки, запрашивающей адрес хоста перед запуском окна с графическим интерфейсом. В будущем можно добавить виджет для этой цели. А пока вот так:
Как только мы получаем адрес и создаем сокет для подключения к нему, мы запускаем поток для получения сообщений, а затем основной цикл для нашего приложения с графическим интерфейсом:
Вот и всё! Теперь наш скрипт клиентской части выглядит вот так:
Да, наше приложение не может тягаться с такими гигантами как: telegram, viber, клиентами xmpp/jabber; однако нам удалось создать простой чат, который каждый может развить в что-то своё: сделать уклон в безопасность(например шифруя передаваемые пакеты) или в хороший ux/ui. Получилась своего рода база для чего-то большего и это круто. Спасибо за прочтение, буду рад любым замечаниям и пожеланиям. Традиционно исходный код программы доступен в моём репозитории на github.
Создание своего мессенджера на Python с нуля

Публиковать могут пользователи с любым рейтингом. Однако!
Приветствуется:
• уважение к читателям и авторам
• простота и информативность повествования
• тег python2 или python3, если актуально
• код публиковать в виде цитаты, либо ссылкой на специализированный сайт
Не рекомендуется:
• допускать оскорбления и провокации
• распространять вредоносное ПО
• просить решить вашу полноценную задачу за вас
Без текста минус нахуй.
3 сентября

О специалистах

Ответ на пост «Бегут года»
Про белорусскую обувь.
В 2006 году, в январе, купила я себе белорусские сапоги. Страшные, как моя жизнь, но зато дешёвые, натуральный мех и натуральная кожа. С виду они здорово напоминали солдатские кирзачи, но в виде ботфортов с отворотами и на высоком каблуке.
Очень скоро поняла, что белорусские обувные мастера владеют секретной технологией изготовления женской модельной обуви по конверсии, на базе танка Т-34. Эти сапоги не реагировали вообще ни на что. Лужи выше щиколоток, грязь, соль, снег, лёд, реагенты — похуй, пляшем! Волшебные сапоги не протекали, не покрывались белёсыми пятнами и даже не скользили, несмотря на высокий каблук. Не шпилька, правда, каблуки эти больше всего напоминали копыта Сатаны, но зато были весьма устойчивы, и ногам было комфортно.
Злоехидные подружки глумились и советовали выкинуть ночью, чтоб никто не видел, как я избавляюсь от позора — я презрительно вышагивала в своих кирзачах по российскому бездорожью, покрывая семью загибами каждую версту. Я ходила в них в лес за грибами и лазила на чердаки заброшенных домов, бегала по скотным дворам и стройкам (у меня была ещё та работёнка, корреспонденты районок поймут) — сапоги даже не морщились, несмотря на то,что они на тот момент были у меня одни-единственные.
Так прошло лет шесть. Я сделала карьеру, я купила себе ещё две пары сапог — «на выход», а эти белорусские неубиваемые говнодавы оставила исключительно для походов по самым диким неудобьям. Сапоги продолжали жить, несмотря ни на что.
Я переехала с ними в 2015-м в Губкин, а в Ростов-на-Дону в 16-м году и пять зим рассекала зимние ростовские лужи. Сапоги продолжали пробег без единого ремонта! Эта девственная парочка за четырнадцать лет ни разу не побывала в руках сапожников!
В прошлом году у одного из них слегка отклеилась подошва, а у второго разошёлся замок. Я не планировала их выбрасывать: как знать, а вдруг ядерная война, укрывшись этими сапогами можно пережить прямое попадание, — но семья взбунтовалась и выкинула мою прелесссть.
Но ничего, мы ещё повоюем! Ведь в 2011-м я купила милые модельные белорусские ботиночки — почти на таком же каблуке. Я ношу их бессменно каждую весну и каждую осень. На дворе заканчивается 2023-й. И мои ботиночки пока что тоже ни разу не были в ремонте.
Добрый Боженька, дай здоровья и долгих лет всем белорусским обувщикам, а если кто из них уже в раю (непременно в раю, не могут такие мастера попасть в ад), то посади их одесную от Тебя и никому больше не доверяй шить Тебе сандалии!
Татары

Ответ на пост «В аэропорту»
У меня была ситуация. Германия. Иду я тихонько из магазина, руки заняты опилками и сеном для хомяка. Сзади два мальчика 13 лет. С виду турки, как на деле фиг знает. Плюются мне в спину из пустой ручки слюнявыми комками бумаги. Раз прилетело. Я смолчала. Второй раз. Я остановилась и решила пропустить их вперед. Они прлходят и запуляют мне прямо в лицо. Ну и тут я разгневалась. Быстро кидаю на асфальт покупки, хватаю ближнего за волосы тяну к низу. Второй отбегает. Оба верещат. Что тип мне конец. Тут идет немец. Я реально начинаю думать, что мне конец и он позвонит в полицию и мне сделают атата что бью детей. Но он такой: молодая фрау, вам помочь отметелить этих ахеревших членов общества?
Я так удивилась, что слова потеряла. Он их отогнал и проводил меня домоц,чтоб в случае слежки мне ничего не сделали.
Не воспитали дома, воспитает улица.

Я просто сказал "да пошло оно всё"

Ушла жена, с работой хз что вообще. И я просто поехал на пляж, искупаться первый раз за 5 лет. Всем радости и добра!
Олды на базе?


19 лет назад.
3 сентября 2004 года, во время спасения заложников в школе №1 города Беслан погибли 10 сотрудников ЦСН ФСБ России. Это были самые большие единоразовые потери Центра.
10 сотрудников в звании от прапорщика до подполковника.
1. Подполковник Дмитрий Александрович Разумовский, «Вымпел». Посмертно удостоен звания Героя России.
2. Подполковник Олег Геннадьевич Ильин, «Вымпел». Посмертно удостоен звания Героя России.
3. Майор Александр Валентинович Перов, «Альфа». Посмертно удостоен звания Героя России.
4. Майор Вячеслав Владимирович Маляров, «Альфа». Посмертно награжден орденом «За заслуги перед Отечеством» IV степени с мечами.
5. Майор Роман Юрьевич Катасонов, «Вымпел». Посмертно награжден орденом «За заслуги перед Отечеством» IV степени с мечами.
6. Майор Михаил Борисович Кузнецов, «Вымпел». Посмертно награжден орденом «За заслуги перед Отечеством» IV степени с мечами.
7. Майор Андрей Витальевич Велько, «Вымпел». Посмертно награжден орденом «За заслуги перед Отечеством» IV степени с мечами.
8. Лейтенант Андрей Алексеевич Туркин, «Вымпел». Посмертно удостоен звания Героя России.
9. Прапорщик Денис Евгеньевич Пудовкин, «Вымпел». Посмертно награжден орденом «За заслуги перед Отечеством» IV степени с мечами.
10. Прапорщик Олег Вячеславович Лоськов, «Альфа». Посмертно награжден орденом «За заслуги перед Отечеством» IV степени с мечами.
Так же более 50 сотрудников Центра получили ранения различной степени тяжести, в том числе тяжелые.










3 сентября

Много текста


Итак, это была моя попытка сделать комикс — рассказ о себе. Эти картинки я нарисовала ещё в сентябре 2022 года. Но дальше процесс не пошёл: со мной всегда был страх поделиться чем-то слишком личным, или я находилась в состоянии, когда рассказ о себе превращался в сплошное нытье, или я находилась в состоянии, когда всё хорошо, и это нытье в черновиках казалось мне чем-то преувеличенным. Как можно понять, мои обычные будни — это эмоциональные качели)
И вот сегодня, в прекрасный Шуфутинов день, я наткнулась на эти черновики и решила выложить их хотя бы в такой текстовый пост (тем более когда многие поставят тег «3 сентября» в игнор, а тут такая я со своим авторским постом 😁😈)Надо сразу отметить, что сейчас я как раз нахожусь в нижней части своей синусоиды настроения, поэтому пост будет пропитан депресснячком.
Я хотела выложить готовый яркий и красочный пост к моему десятилетию пребывания на пикабу (в июне или в июле было 10 лет) но, как уже было сказано, я не могу его закончить по разными причинам. Десять лет. Звучит страшно) Я очень сильно переживаю из-за быстротечности времени. Меня парит мой возраст, я из тех, кто переживает о старении. Мне 32 (я все-таки стала тем, кто забывает возраст:раньше чётко помнила, а после 31 начала путаться, прикольно 😁) Понимаю, что ещё рано ныть, что старая, но эти мысли постоянно со мной. Когда учишься в школе, в универе, каждый год несёт в себе много событий и много перемен, а когда у тебя есть стабильность — дом, работа, обычные будни, то время летит стремительно и незаметно. Потом однажды ты видишь детей своих ровесников, видишь, как они выросли, и понимаешь, что для тебя прошло по ощущениям года два, а для всех — реальных лет 7)
Кстати, о детях) не знаю, чайлдфри ли я, но у меня, слава богу, нет желания рожать и воспитывать детей. Почему слава богу — потому что если бы у меня было это желание, мне бы наверняка было грустно от того, что у меня даже нет мужа, от которого, собственно, надо рожать))
Почему нет мужа. Раньше я думала, что просто не встретила того самого человека, а сейчас понимаю, что дело не в них. Дело во мне. Для начала нужно навести порядок в себе. Я много осознаю, что нужно делать, но не делаю. Всегда думаю: «да, надо!», и это «надо» тянется годами. Это прокрастинация у меня во всем. Я сама себе говорю — так всё, взяла себя в руки! И отвечаю — да, надо!
Почему бросила рисунки. Даже не знаю 🤔 идеи комиксов часто возникают в голове, но до реализации не доходит (держим в голове предыдущий абзац)) часто кажется, что мой шанс упущен, что моё время прошло, что потенциал я свой не реализовала, что, конечно, приводит к грусти. Опять же к осознанности — я понимаю, что всё зависит от меня. Если чего-то хочешь, нужно делать, нужно вкладывать свои силы и время. Осознание есть. Действий нет.
Вы наблюдаете позицию жертвы) Да, знаю, что удобно пребывать в таком режиме. Об этом мне говорит мой психолог. Я наконец-то все-таки продолжила сеансы со специалистом. Я уже общалась с психологами, но это тема отдельных комиксов. Если всё же отброшу лень, то нарисую- это одна из моих любимых историй)) тот случай, когда ты попадаешь вообще не к тому, кто был нужен 😁
Нужно добавить позитива: конечно, моя жизнь это не сплошное уныние и серость. Мне очень помогает музыка. Не могу назвать себя меломаном, который знает все альбомы всех признанных музыкантов, но я действительно получаю удовольствие от песен, которые мне по душе. Очень люблю петь и танцевать. Горланю песни дома. Однажды в домовом чате попросили прекратить концерт, стыдно до сих пор 😁 так что чаще пою в машине.
Мне нравятся социальные игры- такие как мафия или квизы. Такие игры обеспечивают приятный досуг и дарят эмоции от общения с интересными и разными людьми. Именно этими играми я и заполняла свое свободное время, предпочитая их комиксам. И всё было бы вообще круто, если бы я не рассорилась с друзьями как с мафии, так и с квиза)) я сильно привязываюсь к людям, поэтому разрывы сказываются на мне болезненно. Конечно, я не остаюсь одна. У меня всегда есть моя семья и люди, которые не исчезают из жизни, чему я очень благодарна.
Хотела ещё отдельным абзацом высказаться о новом пикабу. За десять лет я тут наблюдала разное. И всегда была в стороне от бундов и прочего. Но тут хочется отметить, что пока я не могу привыкнуть к тому мусору, что мы теперь видим в горячем. Но зато я пошла в отрыв — я ставлю всем подряд минусы, они всё равно ни на что не влияют. Я думаю, мы все привыкнем к этой системе, но эти посты — призывы в свои телеграмм каналы очень раздражают.
Кстати, о телеграмм канале 😁 я давно думаю завести свой, но пока не решилась. Если он Все-таки родится, то я тоже оставлю на него ссылку и буду всех бесить 😁😁
В конце этого своего поста мне хочется поблагодарить всех, кто на меня подписывался, кто лайкал и комментировал мои рисунки. Спасибо за вашу любовь, за вашу обратную связь, это реально цепляет, и помогает. Не теряйте меня, где-то я есть☺️ Всем большое спасибо за внимание, прошу прощения, если забрызгала кого — то своими соплями. Всех обнимаю ☺️
Сейчас я ухожу в отпуск на две недели, приеду, выложу свой маленький комикс о работе, он почти готов, но я не успеваю его доделать — нужно собирать чемодан))
Create a Video Chat/Video Steaming App using Python
![]()
Due to the pandemic the only way to stay connected through the internet. But due to such a huge activity in Advertisement department, data leak and data privacy is a big issue. To overcome the data privacy issues, let us create our own video chat app in order to stay connected with our dear ones and avoid tracking by any of the advertising companies. Previously we created a text chat app now let’s take a step forward and create a video chat app.
Let us look at the code,
We will be using CV2 module of OpenCV library for capturing the video.
It is recommended to create a separate environment to install the required libraries so that nothing interferes with the default environment in case of any errors
Server.py
Client.py
We run the server.py and after it we try to run client.py, pictures are transferred blazingly fast hence creating a video streaming.
Here we are first clicking picture and then converting it from array to bytes format using pickle module
Now we need to provide the buffer size so that the client can receive the data. For this we use the struct module in Python. Here “Q” is the value we can pass in the arguments so that it provides 8 bytes.
We pack the data using the pack() function available in struct module, the first 8 bytes corresponds to the size of the file.
We use the unpack function to unpack the packed data.
Instead, we can also use the flatten() and tostring() functions.
Now, let us use multi-threading and create a smooth video chat app. We will be starting 4 threads in Client A and Client B each simultaneously(2 threads for video streaming and receiving and 2 audio streaming and listening). One thread will send the video and other will receive the video.
We will be using PyAudio library for audio transfer. Now, installing it can be tricky so install it using the following command only or else you might end up breaking your head and still wont be able to find a stable version.
For this we need Anaconda distribution to be installed. Anaconda has an updated bug free version of PyAudio library.
Client A
Client B
Here in PyAudio library, we need to specify the format, channels, rate, input and frames_per_buffer.
We create a separate socket for the audio so that it doesn’t intervene with the video stream.
Пишем свой мессенджер P2P

На фоне обсуждения будущего интернет мессенджеров и прочтения статьи «Почему ваш любимый мессенджер должен умереть», решил поделиться своим опытом создания P2P приложения для общения независимо от сторонних серверов. Точнее — это просто заготовка, передающая одно сообщение от клиента серверу, дальнейшее расширение функционала зависит только от Вашей фантазии.
В этой публикации мы напишем 3 простых приложения для связи P2P из любой точки Земного шара — клиент, сервер и сигнальный сервер.
Нам понадобится:
— один сервер с белым статическим IP адресом;
— 2 компьютера за NAT с типом соединения Full Cone NAT (либо 1 компьютер с 2-мя виртуальными машинами);
— STUN-сервер.
Full Cone NAT — это такой тип преобразования сетевых адресов, при котором существует однозначная трансляция между парами «внутренний адрес: внутренний порт» и «публичный адрес: публичный порт».
Вот, что мы можем прочесть о STUN-сервере на Wiki:
При решении задачи использовались следующие питоновские модули: socket, twisted, stun, sqlite3, os, sys.
Для обмена данными, как между Сервером и Клиентом, так и между Сервером, Клиентом и Сигнальным Сервером — используется UDP протокол.
В общих чертах механизм функционирования выглядит так:
Сервер <-> STUN сервер
Клиент <-> STUN сервер
Сервер <-> Сигнальный Сервер
Клиент <-> Сигнальный Сервер
1. Клиент, находясь за NAT с типом соединения Full Cone NAT, отправляет сообщение на STUN сервер, получает ответ в виде своего внешнего IP и открытого PORT;
2. Сервер, находясь за NAT с типом соединения Full Cone NAT, отправляет сообщение на STUN сервер, получает ответ в виде своего внешнего IP и открытого PORT;
При этом, Клиенту и Серверу известен внешний (белый) IP и PORT Сигнального Сервера;
3. Сервер отправляет на Сигнальный Сервер данные о своих внешних IP и PORT, Сигнальный Сервер их сохраняет;
4. Клиент отправляет на Сигнальный Сервер данные о своих внешних IP и PORT и id_destination искомого Сервера, для которого ожидает его внешний IP, PORT.
Сигнальный Сервер их сохраняет, осуществляет поиск по базе, используя id_destination и, в ответ, отдает найденную информацию в виде строки: ‘id_host, name_host, ip_host, port_host’;
5. Клиент принимает найденную информацию, разбивает по разделителю и, используя (ip_host, port_host), отправляет сообщение Серверу.
Приложения написаны на Python версии 2.7, протестированы под Debian 7.7.
Создадим файл server.py с содержимым:
Заполним соответствующие поля разделов: «Внешний IP и PORT СИГНАЛЬНОГО СЕРВЕРА» и «IP и PORT этого КЛИЕНТА».
Создадим файл client.py с содержимым:
Заполним соответствующие поля разделов: «Внешний IP и PORT СИГНАЛЬНОГО СЕРВЕРА» и «IP и PORT этого КЛИЕНТА».