Не работают сокеты в python

Обновлено: 06.07.2024

Сегодня мы рассмотрим пример программирования сокетов Python. Мы создадим серверные и клиентские приложения на Python.

Программирование сокетов

Чтобы понять программирование сокетов Python, нам нужно знать о трех интересных темах – Socket Server, Socket Client и Socket.

Итак, что такое сервер? Сервер – это программное обеспечение, которое ожидает запросов клиентов и обслуживает или обрабатывает их соответственно.

С другой стороны, клиент запрашивает эту услугу. Клиентская программа запрашивает некоторые ресурсы к серверу, и сервер отвечает на этот запрос.

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

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

Пример

Ранее мы говорили, что клиент сокета запрашивает некоторые ресурсы у сервера, и сервер отвечает на этот запрос.

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

Сервер сокетов

Мы сохраним программу сервера сокетов, как socket_server.py. Чтобы использовать соединение, нам нужно импортировать модуль сокета.

Затем последовательно нам нужно выполнить некоторую задачу, чтобы установить соединение между сервером и клиентом.

Мы можем получить адрес хоста с помощью функции socket.gethostname(). Рекомендуется использовать адрес порта пользователя выше 1024, поскольку номер порта меньше 1024 зарезервирован для стандартного интернет-протокола.

Смотрите приведенный ниже пример кода сервера:

Итак, наш сервер сокетов работает на порту 5000 и будет ждать запроса клиента. Если вы хотите, чтобы сервер не завершал работу при закрытии клиентского соединения, просто удалите условие if и оператор break. Цикл while используется для бесконечного запуска серверной программы и ожидания клиентского запроса.

Клиент сокета

Мы сохраним клиентскую программу сокета python как socket_client.py. Эта программа похожа на серверную, за исключением привязки.

Основное различие между серверной и клиентской программой состоит в том, что в серверной программе необходимо связать адрес хоста и адрес порта вместе.

Смотрите ниже пример кода клиента сокета:

Вывод

Чтобы увидеть результат, сначала запустите программу сервера сокетов. Затем запустите клиентскую программу. После этого напишите что-нибудь из клиентской программы. Затем снова напишите ответ от серверной программы.

Наконец, напишите «до свидания» из клиентской программы, чтобы завершить обе программы. Ниже короткое видео покажет, как это работало на моем тестовом прогоне примеров программ сервера сокетов и клиента.

python socket programming, python socket server

Обратите внимание, что сервер сокетов работает на порту 5000, но клиенту также требуется порт сокета для подключения к серверу. Этот порт назначается случайным образом при вызове клиентского соединения. В данном случае это 57822.

Недавно я вернулся из отпуска, и мой базовый сервер сокетов python 2 теперь не может общаться с клиентами по локальной сети. Сервер находится на mac, а клиент - мой малиновый pi или мой Windows 7. Я упростил здесь код сервера и клиента, чтобы привести пример:

сервер

клиент

Вопрос

Что здесь происходит? Я получаю локальный IP-адрес, но сценарии по-прежнему не могут общаться. Это может быть проблема с ОС?

БОЛЬШЕ ИНФОРМАЦИИ

а. Я смог выполнить ping PI с моего терминала Mac:

с. Мой компьютер смог PING мой mac. Мой Mac смог выполнить ping мой компьютер

Мой Mac Firewall отключен. Я проверил [Raspberry Pi Stackexchange Site], чтобы узнать, имеет ли PI брандмауэр.

Я добавлю дополнительную информацию, как только проверю машину для Windows

Запуская оба сценария локально, им удается подключаться и общаться на моей машине. Вы столкнулись с сетевой проблемой, которую нужно легко отлаживать.

Неверная привязка. На сервере распечатайте HOST, который вы получите. Если на сервере имеется более одного IP-адреса, вы можете попытаться связать его с неправильным. Вы также можете изменить его на "0.0.0.0" (только на стороне сервера) и посмотреть, работает ли это.

Брандмауэр. Любая из сторон может блокировать связь tcp на уровне ОС. Отладка выполняется через Wireshark на Windows и tcpdump в unix. Начните снюхать, запустите свой код и посмотрите, что пошло не так. Скорее всего, вы увидите, что клиент отправляет SYN пакет, но сервер не сможет ответить с помощью пакета SYN|ACK . Если вы видите, что пакет SYN достигает сервера, попробуйте полностью завершить брандмауэр сервера и повторите попытку. Если нет, то клиенту запрещается исходящая связь (менее вероятно), и вам нужно будет отключить его брандмауэр.

Использовать порт. Попробуйте удалить SO_REUSEADDR для отладки и посмотреть, что-то изменится.

Исключения. Убедитесь, что вы не игнорируете какие-либо исключения из своих сокетов.

Для создания сокета существует функция, называемая socket . Она принимает аргументы family , type и proto (подробнее см. в документации). Чтобы создать TCP-сокет, нужно использовать socket.AF_INET или socket.AF_INET6 для family и socket.SOCK_STREAM для type .

Пример Python socket:

Функция возвращает объект сокета, который имеет следующие основные методы:

  • bind()
  • listen()
  • accept()
  • connect()
  • send()
  • recv()

Здесь мы создаем серверный сокет, привязываем его к localhost и 50000-му порту и начинаем прослушивать входящие соединения.

Чтобы принять входящее соединение, мы вызываем метод accept() , который будет блокироваться до тех пор, пока не подключится новый клиент. Когда это произойдет, метод создаcт новый сокет и вернет его вместе с адресом клиента.

Затем он в бесконечном цикле считывает данные из сокета партиями по 1024 байта, используя метод recv() , пока не вернет пустую строку. После этого он отправляет все входящие данные обратно, используя метод sendall() , который в свою очередь многократно вызывает метод send() . И после этого сервер просто закрывает клиентское соединение. Данный пример может обрабатывать только одно входящее соединение, потому что он не вызывает accept() в цикле.

Код на стороне клиента выглядит проще:

Вместо методов bind() и listen() он вызывает только метод connect() и сразу же отправляет данные на сервер. Затем он получает обратно 1024 байта, закрывает сокет и выводит полученные данные.

Все методы сокета являются блокирующими. Это значит, что когда метод считывает данные из сокета или записывает их в него, программа больше ничего делать не может.

Для решения этой проблемы существует так называемый способ асинхронного взаимодействия с сокетами. Основная идея состоит в том, чтобы делегировать поддержание состояния сокета операционной системе и позволить ей уведомлять программу, когда есть данные для чтения из сокета или когда сокет готов к записи.

Существует множество интерфейсов для разных операционных систем:

Все они примерно одинаковы, поэтому давайте создадим сервер с помощью Python select. Пример Python select :

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

Создание серверного сокета происходит так же, кроме одной строки: server.setblocking(0) . Это нужно для того, чтобы сокет не блокировался. Такой сервер более продвинутый, поскольку он может обслуживать более одного клиента. Главная причина заключается в сокетах selecting :

Этот вызов (если не передан аргумент timeout ) блокирует программу до тех пор, пока какие-либо из переданных сокетов не будут готовы. В этот момент вызов вернет три списка сокетов для указанных операций.

Так работают сокеты на низком уровне. Однако в большинстве случаев нет необходимости реализовывать настолько низкоуровневую логику. Рекомендуется использовать более высокоуровневые абстракции, такие как Twisted, Tornado или ZeroMQ, в зависимости от ситуации.

Я недавно вернулся из отпуска, и мой базовый сервер сокетов python 2 теперь не может общаться с клиентами через LAN. Сервер находится на компьютере mac, а клиент-на моей машине raspberry pi или windows 7. Я упростил код сервера и клиента здесь, чтобы привести пример:

Сервер

Клиент

Вопрос

Что здесь происходит? Я получаю локальный IP, но скрипты все еще не могут общаться. Может быть, это проблема с OS-м?

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ

Я смог пропинговать PI с моего Mac terminal:

c. Мой PC смог PING моем Mac. Мой Mac смог пропинговать мой PC

Брандмауэр компьютер Mac выключен. Я буду проверять на [сайте клиент StackExchange Raspberry Pi], чтобы увидеть, если PI брандмауэр.

Я добавлю больше информации, как только протестирую свою машину windows

2 ответа

Кто-нибудь знает, можно ли адаптировать один из этих мессенджеров, чтобы использовать их также над LAN?

Я хотел бы написать сценарий python для сбора данных из серийного номера над lan, но я не могу найти место, чтобы начать с IPMI. Я просмотрел привязки OpenIPMI python, но там, похоже, нет никакой документации. Возможно, я могу использовать модуль подпроцесса и ipmitool? Хотя я не уверен, что это.

Запустив оба сценария локально, они умудряются подключаться и общаться на моей машине. Вы столкнулись с сетевой проблемой, которую должно быть легко отладить.

Неправильный Переплет. На сервере выведите HOST, который вы получите. Если на сервере более одного IP, вы можете попытаться привязать не к тому. Вы также можете изменить его на " 0.0.0.0 " (только на стороне сервера) и посмотреть, работает ли это.

Брандмауэр. Любая из сторон может блокировать связь tcp на уровне OS. Отладка выполняется через Wireshark на Windows и tcpdump на unix. Начните нюхать, запустите свой код и посмотрите, что пошло не так. Скорее всего, вы увидите, что клиент отправит пакет SYN , но сервер не сможет ответить пакетом SYN|ACK . Если вы видите, что пакет SYN достигает сервера, попробуйте полностью отключить брандмауэр сервера и повторите попытку. Если нет, то клиенту запрещена исходящая связь (менее вероятно), и вам нужно будет отключить его брандмауэр.

Используется порт. Попробуйте удалить SO_REUSEADDR для отладки и посмотрите, не изменится ли что-нибудь.

Исключения. Убедитесь, что вы не игнорируете никаких исключений из своих сокетов.

Ваш код работает нормально я сделал некоторые незначительные исправления и объяснил их в комментариях внутри кода:

SERVER:

CLIENT:

Приведенный выше код просто отлично работал для меня, я уверен, что это будет и для вас, так как я испытал ту же проблему. Найденные ошибки я поместил в комментарии внутри кода, посмотрите.

У меня есть базовый сценарий ZeroMQ, состоящий из двух издателей и подписчика. Это прекрасно работало на локальном компьютере, пока я не решил разделить все процессы на разных компьютерах в моем LAN. Вот как я создаю сокеты ZeroMQ (упрощенный код Python): (Процесс подписчика, запущенный на машине.

Я создаю мессенджер, который является таким же, как IP Messenger в Python 2.7 и Windows. Я хочу использовать ту же функциональность, что и IP Messenger, чтобы найти системы, работающие с одним и тем же программным обеспечением более LAN, но я не могу понять эту технику. Может ли кто-нибудь помочь.

Похожие вопросы:

Я пытаюсь добавить многопользовательские возможности в созданную мной игру. Я прочитал учебник Java по сокетам, но все еще не могу достичь желаемой функциональности. В аналогичном посте другой.

Мне пришлось использовать Source Safe на работе, и он взорвался. Я бы хотел переключиться на TortiseSVN, но, по-видимому, при работе над LAN все может испортиться? Это правда? Есть ли вообще способ.

Привет, я делаю многопользовательскую игру Java, и все работает нормально. У него есть все, что кому-то нужно, но я нашел проблему, он использует ServerSocket для сервера и сокет для клиентов.

Кто-нибудь знает, можно ли адаптировать один из этих мессенджеров, чтобы использовать их также над LAN?

Я хотел бы написать сценарий python для сбора данных из серийного номера над lan, но я не могу найти место, чтобы начать с IPMI. Я просмотрел привязки OpenIPMI python, но там, похоже, нет никакой.

У меня есть базовый сценарий ZeroMQ, состоящий из двух издателей и подписчика. Это прекрасно работало на локальном компьютере, пока я не решил разделить все процессы на разных компьютерах в моем.

Я создаю мессенджер, который является таким же, как IP Messenger в Python 2.7 и Windows. Я хочу использовать ту же функциональность, что и IP Messenger, чтобы найти системы, работающие с одним и тем.

Я пытался использовать необработанный сокет на python 3.5 асинхронным способом. Я нашел библиотеку asyncore, где мы можем использовать необработанные сокеты, но, похоже, она устарела, и библиотека.

Я работаю над проектом, где мне нужны сокеты. Поэтому я реализовал соединение с сокетом и работал над отладкой, но не в сборке выпуска. Мне нужно, чтобы сокеты работали над сборкой выпуска без.

Читайте также: