Модуль сокета (python) работает, но не использует указанный номер порта? - PullRequest
0 голосов
/ 17 марта 2019

Я использую модуль socket из Python 3.7 (это не должно иметь значения, так как я пытался активировать другую версию Python из другой версии venv).

Проблема в том, что я создал TCP-соединение, прослушивающее порт 65432, произвольное число, которое я выбрал для этой простой демонстрации.

server.py выглядит следующим образом:

import socket

HOST = '127.0.0.1' # Standard loopback interface address (localhost)
PORT = 65432 # Non-privileged ports are > 1024

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen() 
    conn, addr = s.accept() 
    with conn:
        print('Connected by', addr)
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)

client.py относительно прост, поскольку он устанавливает соединение с 127.0.0.1:65432.

import socket

HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 65432 # Port used by the server

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    # Send its message and then read the server's reply and prints it
    s.sendall(b'Hello, world')
    data = s.recv(1024)

print('Received', repr(data))

Выполнение server.py, чтобы открыть порт 65432 для прослушивания (в первой консоли), а затем выполнение client.py для отправки простого сообщения 'hello world' (во второй консоли).Вот что было напечатано на первой консоли:

Connected by ('127.0.0.1', 56051)

Пока все хорошо.Порт 56051 подключается к порту 65432, верно?

Я выполняю netstat -am (утилита командной утилиты для просмотра состояния сокетов на хост-компьютере) и обнаружил это:

Active Internet connections (including servers)
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)    
tcp4       0      0  127.0.0.1.51495        *.*                    LISTEN 

Вместо 127.0.0.1.65432в качестве локального адреса вместо него используется порт 51495.

Выполняется еще одна проверка, на этот раз запускается lsof -i -n:

COMMAND     PID     FD   TYPE             DEVICE SIZE/OFF NODE NAME
Code\x20H 51214    37u  IPv4 0x1af15eb424ba89f3      0t0  TCP 127.0.0.1:51495 (LISTEN)

Обе проверки подтвердили, что порт 51495 работаетиспользуется вместо 65432, как указано в моих сценариях server.py и client.py.Есть ли советы или советы?Большое спасибо заранее!

Ответы [ 2 ]

0 голосов
/ 18 марта 2019

Как указывал @ottomeister, имя процесса было первой раздачей. Имя процесса должно было быть Python, но вместо него отображался VS Code, что указывает на то, что порт 51495 открыт процессом VS Code и не имеет ничего общего с нашим кодом модуля сокета.

То, как был настроен менеджер контекста, означает, что соединение будет закрыто в тот момент, когда будет выполнена последняя строка (в данном случае socket.sendall()). Поэтому сокет сервера больше не активен.

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

Когда я слежу за состоянием портов, когда порт сервера открыт (до того, как сокет клиента соединится с ним), тогда достаточно 65432, что появилось. Это подтверждается в netstat, lsof, а также nmap. Простое утверждение печати после успешного подключения к сокету также подтвердит, что порт сервера фактически использует указанный номер порта, который равен 65432.

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

0 голосов
/ 17 марта 2019

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

Connected by ('127.0.0.1', 56051)

отображается на первой консоли, которая является консолью вашего сервера.таким образом, этот номер порта является номером порта клиентского сокета.не сокет сервера.

В коде сервера, который вы используете, s.accept (), эта функция возвращает временный идентификатор подключения и адрес клиента, который сделал запрос.то же самое, что вы пытаетесь напечатать в коде.

...