Python Почему не выполняется нужное действие в скрипте?

БлагоЯр

Новый пользователь
Сообщения
8
Реакции
0
Всем доброго времени суток.
Есть такой скрипт, который слушает порт, если на этот порт отправить magic пакет, то в зависимости от операционной системы должна выполняться определённая команда.
В Windows это работает без проблем, запускаю в Arch, порт слушается (это видно по netstat -tulpan), но при посылке пакета ничего не происходит.
Если для проверки оставить только команду os.system("reboot"), то она выполняется.
Почему так?
Python:
import socket
import os
import logging
import psutil
 
WOL_PORT = 9999
INTERFACE_NAME = "My Lan"
INTERFACE_NAME_ARCH = "enp37s0"
 
logging.basicConfig(format="%(levelname)s: %(asctime)s %(message)s", level=logging.INFO)
logger = logging.getLogger(__name__)
 
 
def get_ip_mac_address(interface_name: str) -> tuple:
    ip_addr = mac_addr = None
 
    for item in psutil.net_if_addrs()[interface_name]:
        addr = item.address
 
        if "." in addr:
            ip_addr = addr
        elif ("-" in addr or ":" in addr) and "::" not in addr:
            mac_addr = addr.replace(":", "-").upper()
 
    if not ip_addr or not mac_addr or ip_addr == "127.0.0.1":
        raise "Не удалось получить IP или MAC-адрес сетевого интерфейса"
 
    return ip_addr, mac_addr
 
 
def assemble_wol_packet(mac_address: str) -> str:
    return f'{"FF-" * 6}{(mac_address + "-") * 16}'
 
 
def check_is_wol_packet(raw_bytes: bytes, assembled_wol_packet: str) -> int:
    decoded_packet_data = "-".join(f"{byte:02x}" for byte in raw_bytes).upper() + "-"
 
    if decoded_packet_data == assembled_wol_packet:
        return 1
 
    return 0
 
 
def run_udp_port_listener(port: int, interface_name: str):
    ip_addr, mac_addr = get_ip_mac_address(interface_name)
 
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_socket.bind((ip_addr, port))
    logger.info(f"Listening on {ip_addr}:{port}")
 
    assembled_wol_packet = assemble_wol_packet(mac_addr)
 
    while True:
        data, _ = server_socket.recvfrom(1024)
 
        is_wol_packet = check_is_wol_packet(data, assembled_wol_packet)
 
        if is_wol_packet == 1:
            if os.name == "posix":
                os.system("reboot")
            elif os.name == "nt":
                os.system(
                    "shutdown -r -t 0 -f"
                )
 
 
if os.name == "posix":
    run_udp_port_listener(WOL_PORT, INTERFACE_NAME_ARCH)
elif os.name == "nt":
    run_udp_port_listener(WOL_PORT, INTERFACE_NAME)
 
А если проверить ручками, порт 9999 не блокируется? Не занят? Названия интерфейсов совпадют?

Похоже, что у вас проверка на ошибку подключения не работает, по версии chatgpt нужно использовать raise Exception, а не просто raise
 
порт 9999 не блокируется?
Ну я так подозреваю, что если бы был занят, то netstat его не показывал, как прослушиваемый.
Не занят? Названия интерфейсов совпадют?
Точно не занят, интерфейс указанный в начале скрипта и по ip a вставлял методом copy-paste, в этом ошибки быть не может.
При попытке запустить так, получаю syntax error.
проверить ручками
Ну пробовал через telnet 192.168.0.2 9999 и localhost тоже пробовал, рефьюзит.
 
Последнее редактирование:
А check_is_wol_packet там вообще 1 возвращает?

Напишите что-нибудь по-проще и проверьте:

Python:
import socket

# Create a UDP socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# Bind the socket to an address and port
server_socket.bind(('localhost', 9999))

print("Server is listening...")

# Receive data
data, addr = server_socket.recvfrom(1024)
print(f"Received message: {data.decode()} from {addr}")

Порт поменять пробовали на что-то другое?
 
Порт поменять пробовали на что-то другое?
Да, пробовал 55555
Напишите что-нибудь по-проще и проверьте:
Тоже ничего не происходит. Я так понимаю должно появится сообщение
Код:
Received message: {data.decode()} from {addr}
при получении пакета, но нет.
А check_is_wol_packet там вообще 1 возвращает?
Как проверить?
 
А вы чем проверяете? telnet - это протокол TCP. А у вас в коде SOCK_DGRAM - это UDP. Поменяйте на SOCK_STREAM.

Если нужно слать UDP, то например через netcat:
Код:
echo "Your message" | nc -u localhost 9999
 
Последнее редактирование:
А у вас в коде SOCK_DGRAM - это UDP. Поменяйте на SOCK_STREAM.
Код:
INFO: 2024-11-01 20:59:20,316 Listening on 192.168.0.2:55555
Traceback (most recent call last):
  File "/home/blagoyar/Scripts/WoL 9999 [Reboot to Arch].py", line 66, in <module>
    run_udp_port_listener(WOL_PORT, INTERFACE_NAME_ARCH)
  File "/home/blagoyar/Scripts/WoL 9999 [Reboot to Arch].py", line 54, in run_udp_port_listener
    data, _ = server_socket.recvfrom(1024)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [Errno 107] Transport endpoint is not connected
А вы чем проверяете? telnet - это протокол TCP
Ну да, чёт я завтыкал :)
Тогда даже не знаю, чем UDP проверять.
 
OSError: [Errno 107] Transport endpoint is not connected
Я не являюсь кодером в пайтон, но по-моему у вас слушатель вообще неправильно формируется.
Должно быть bind, listen, accept, затем recv. А у вас часть функций вообще пропущена.
См. примеры:

Тогда даже не знаю, чем UDP проверять.
Выше же написал пример с netcat.
 
Выше же написал пример с netcat.
Так я тоже лог ошибки дал, когда я меняю на SOCK_STREAM.
А у вас часть функций вообще пропущена
Так всё бы ничего, но в Windows чётко всё работает.
Мне что кажется есть какая-то закавыка с арчем.
Либо python на Win отличается чем-то от Linux.
 
Возможно, Windows не следует строго протоколу, там где у вас опущены шаги подключения.
Если по примерам выше тоже не помогло, то по пайтону вам лучше спросить на других более специализированных форумах.
У нас эта ветка форума почти мертва.
 
Назад
Сверху Снизу