Python: сетевые приложения

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Python: сетевые приложения

Непрочитанное сообщение Olej » 17 дек 2023, 15:53

Это продолжение вот этой затеи: Go: сетевые приложения
Это (задумывается) небольшой цикл дополнений к 2-му изданию книги:
Затея состоит в том, чтобы сравнительно показать как (насколько проще) реализуется TCP коннект (уровень L3 Linux) в более поздних, разных, языках программировани ... в сравнении с классикой C, да и C++ тоже.

P.S. По сегодняшнему состоянию дел, всё в Python будем иметь в виду Python3, про Python2 есть смысл вспоминать только в рассмотрении приложений, созданных в предыдущие годы, см. Python: версии языка.

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ which python
/usr/bin/python

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ python --version
Python 3.10.12

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Python: сетевые приложения

Непрочитанное сообщение Olej » 17 дек 2023, 16:02

Olej писал(а):
17 дек 2023, 15:53
в более поздних, разных, языках
В отношении Python возьму за базовую реализацию вот эту публикацию:
Руководство по программированию сокетов на Python. От введения до работающего примера
26 сен 2022 в 23:39
По-моему, очень прилично ... даже не сколько в примерах кода (это и та понятно), сколько в осмысленном описании того что происходит.

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ python ./echo_serv.py 
Connected by ('127.0.0.1', 53192)

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ python echo_cli.py 
Received b'Hello, world'

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ chmod a+x echo*.py

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ chmod a+x echo*.py

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ ./echo_serv.py
Connected by ('127.0.0.1', 53164)

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ ./echo_cli.py
Received b'Hello, world'

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Python: сетевые приложения

Непрочитанное сообщение Olej » 17 дек 2023, 19:50

Olej писал(а):
17 дек 2023, 16:02
В отношении Python возьму за базовую реализацию вот эту публикацию:
Сервер (по аналогии с Go: сетевые приложения), последовательный, однонитевой:

Код: Выделить всё

#!/usr/bin/python3
import socket

HOST = "127.0.0.1"             # loopback interface address (localhost)
PORT = 52500                   # port to listen with Python

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    try:
        s.bind((HOST, PORT)) 
    except OSError:
        print("address already in use")
        quit()    
    s.listen()
    while True:
        print('waiting on port', PORT)
        try:
            conn, addr = s.accept()
        except KeyboardInterrupt:
            print()
            quit()
        with conn:
            while True:
                data = conn.recv(1024)
                if not data:       # клиент закрыл сокет
                    break
                conn.sendall(data)
        conn.close()       
Обработка ошибок, хоть они и засоряют ясность изложения, сделаны по минимум, только чтобы на терминал на сыпались назойливые аврийные сообщения, которые так любит Python.
Вложения
echo_serv.py
(784 байт) 9 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Python: сетевые приложения

Непрочитанное сообщение Olej » 17 дек 2023, 19:57

Olej писал(а):
17 дек 2023, 19:50
последовательный, однонитевой:

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ ./echo_serv.py 
waiting on port 52500
waiting on port 52500
waiting on port 52500
waiting on port 52500
^C

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ nc 127.0.0.1 52500
123
123
4563
4563
^C

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ socat tcp4:127.0.0.1:52500 STDOUT
sdfg
sdfg
xcnnx
xcnnx
^C

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ telnet 127.0.0.1 52500 
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
123
123
string
string
строка
строка
^]
telnet> quit
Connection closed.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Python: сетевые приложения

Непрочитанное сообщение Olej » 17 дек 2023, 20:06

Olej писал(а):
17 дек 2023, 19:50
Обработка ошибок, хоть они и засоряют ясность изложения, сделаны по минимум, только чтобы на терминал на сыпались назойливые аврийные сообщения, которые так любит Python.

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ ./echo_serv.py
waiting on port 52500
Запуск 2-го экземпляра:

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ ./echo_serv.py
address already in use
Вместо малоосмысленного дампа Python :evil:

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Python: сетевые приложения

Непрочитанное сообщение Olej » 17 дек 2023, 20:17

Olej писал(а):
17 дек 2023, 19:50
Сервер
Клиент...
Пока в таком виде что он знает только 1 фиксированный порт своего спаренного сервера (52500) ... а надо ли вообще делать? - я не собираюсь именно на Python делать другие классы обслуживания сервером: параллельный, с очередями...

Код: Выделить всё

#!/usr/bin/python3
import socket
import sys

HOST = "127.0.0.1"  # The server's hostname or IP address
PORT = 52500        # the port used by the Python server

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    try:                                # пробуем присоединиться
        s.connect((HOST, PORT))
    except ConnectionRefusedError:
        print("no server available")
        quit()
    while True:
        sys.stdout.write("> " )
        sys.stdout.flush()
        try:
            str = sys.stdin.readline()
        except KeyboardInterrupt:       # ^C - завершение работы
            print("\r")
            break 
        if str == '':                   # ^D - завершение работы
            sys.stdout.write('\r')
            break
        if "\n" == str:                 # Enter - завершение работы
            break
        s.sendall(bytes(str, "UTF-8"))
        data = s.recv(1024)
        print(" ", data.decode("UTF-8"), end='')
И здесь 90% кода - это обработка ошибок чтоб не морочили голову: завершение ввода, отсутсвие сервера ...

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ ./echo_cli.py 
no server available
Вложения
echo_cli.py
(1.01 КБ) 8 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Python: сетевые приложения

Непрочитанное сообщение Olej » 17 дек 2023, 20:29

Olej писал(а):
17 дек 2023, 20:17
Клиент...
И здесь поведение Python клиента совершенно совпадает с поведением естественных тестеров, CLI утилит Linux:

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ ./echo_cli.py
> 123 456
  123 456
> русская строка
  русская строка
>

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ nc 127.0.0.1 52500
123 4567
123 4567
русская строка
русская строка
^C

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ socat tcp4:127.0.0.1:52500 STDOUT
123 456 7
123 456 7
русская строка
русская строка
^C
Здесть проверка и на:
- разбивака строки нп слова пробелом
- и кодировка UTF-8 UNICODE - рускоязычная строка.
... да что там русская :!: :lol: :

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ ./echo_cli.py 
> नमस ्त े
  नमस ्त े
> Dobrý den
  Dobrý den
> لسلام عليكم
  لسلام عليكم
> こんにちは
  こんにちは
> 今日は
  今日は
> 안녕하세요
  안녕하세요
> 你好
  你好
> 

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Python: сетевые приложения

Непрочитанное сообщение Olej » 17 дек 2023, 22:32

Olej писал(а):
17 дек 2023, 20:29
и кодировка UTF-8 UNICODE - рускоязычная строка.
Единственно что меня смутило ... :-o - это когда клиентом выступает telnet:

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ telnet 127.0.0.1 52500
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
12 34 56
12 34 56
строка
строка
строка 2
строка 2
русская строка
qwerty
qwerty
^]
telnet> quit
Connection closed.
Загадочная строка "русская строка" которая ничего не возвратила :-o
Проверил: то же самое имеет место и при работе telnet с эхо-сервером на Go.
Буду разбираться. :-(
Набрал ещё некоторые русскоязычные строки:

Код: Выделить всё

olej@R420:~/2023/own.BOOKs/NET.2/Nexamples.WORK/Python$ telnet 127.0.0.1 52500
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
строка
строка
русская
рус
русс
руская
руслая
опять строка
sfasd
sfasd
строка
строка
опять строка
^]
telnet> quit
Connection closed.
Некоторые эхо-возвращаются (которые удваиваются, но другие пропадают, и никакого ответа, даже пустой строки).

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Python: сетевые приложения

Непрочитанное сообщение Olej » 19 дек 2023, 12:39

Olej писал(а):
17 дек 2023, 22:32
Загадочная строка "русская строка" которая ничего не возвратила
Собственно, ничего загадочного - пришлось вспомнить отганизацию telnet - 4.5.3 Удаленный доступ (Telnet).
В режиме построчной передачи (mode line) в потоке могут идти символы управления (команд), в посимвольном режиме (mode char) это чистый поток байт... но это не наш случай.
Запускаю эхо-сервер так (shell: эхо-сервер TCP):

Код: Выделить всё

olej@R420:~$ nc -l -p 50002 -e '/bin/cat'
И работаем с ним через telnet:

Код: Выделить всё

olej@R420:~$ telnet 127.0.0.1 50002
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
р
р
у
с
с
к
к
а
а
я
с
с
т
т
о
о
^]
telnet> mode char
ррууссккааяя  ссттррооккаа^]
telnet> mode line
123
123
^]
telnet> quit
Connection closed.
Русские буквы 'у' и 'я' не вызывают эхо в линейном режиме.
Буква 'х' искажается и возвращается непечатным символом.
Не знаю на счёт всех, не проверял.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Python: сетевые приложения

Непрочитанное сообщение Olej » 19 дек 2023, 12:51

Olej писал(а):
19 дек 2023, 12:39
могут идти символы управления (команд)

Код: Выделить всё

olej@R420:~$ telnet
telnet> display
will flush output when sending interrupt characters.
won't send interrupt characters in urgent mode.
won't read the telnetrc files.
won't map carriage return on output.
will recognize certain control characters.
won't turn on socket level debugging.
won't print hexadecimal representation of network traffic.
won't print user readable output for "netdata".
won't show option processing.
won't print hexadecimal representation of terminal traffic.

echo            [^E]
escape          [^]]
rlogin          [off]
tracefile       "(standard output)"
flushoutput     [^O]
interrupt       [^C]
quit            [^\]
eof             [^D]
erase           [^?]
kill            [^U]
lnext           [^V]
susp            [^Z]
reprint         [^R]
worderase       [^W]
start           [^Q]
stop            [^S]
forw1           [off]
forw2           [off]
ayt             [^T]
telnet> quit

Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 7 гостей