Сетевое программирование на Python3

Python предоставляет сетевые службы на двух уровнях:

  • Низкоуровневые сетевые службы поддерживают базовые сокеты, предоставляя стандартный API BSD Sockets, который может получать доступ ко всем методам интерфейса сокетов нижележащей операционной системы.
  • Высокоуровневый модуль сетевых служб SocketServer предоставляет классы, ориентированные на сервер, которые могут упростить разработку сетевых серверов.

Что такое сокет?

Сокет, также известный как «сокет», используется приложениями для отправки запросов в сеть или ответа на сетевые запросы, обеспечивая связь между хостами или между процессами на одном компьютере.


Функция socket()

В Python мы используем функцию socket() для создания сокета, а синтаксис следующий:

socket.socket([family[, type[, proto]]])

Parameters

  • family: Семейство сокетов может быть AF_UNIX или AF_INET
  • type: Тип сокета можно разделить в зависимости от того, ориентирован ли он на соединение или не требует соединения:SOCK_STREAMилиSOCK_DGRAM
  • proto: обычно оставляется пустым, по умолчанию равно 0.

Встроенные методы объекта Socket

Функция Описание
Сокет на стороне сервера
s.bind() Привязывает адрес (host, port) к сокету. В AF_INET адрес представляется в виде кортежа (host, port).
s.listen() Запускает прослушивание TCP. backlog задаёт максимальное число соединений, которые операционная система может поместить в очередь до отказа в соединениях. Это значение должно быть не меньше 1, и для большинства приложений достаточно задать его равным 5.
s.accept() Пассивно принимает TCP-подключения клиентов, (блокируясь) ожидая поступления соединения
Сокет на стороне клиента
s.connect() Активно инициализирует соединение с TCP-сервером. Обычно формат адреса — кортеж (hostname, port). Если соединение не удаётся, возвращается socket.error.
s.connect_ex() Расширенная версия функции connect(), возвращает код ошибки при неудаче вместо возбуждения исключения
Сокетные функции общего назначения
s.recv() Принимает данные TCP, возвращаемые в виде строки. bufsize задаёт максимальный объём данных для приёма. flag предоставляет дополнительную информацию о сообщении и обычно может игнорироваться.
s.send() Отправляет данные TCP, передавая данные из строки в подключённый сокет. Возвращаемое значение — количество отправленных байтов, которое может быть меньше размера строки в байтах.
s.sendall() Полностью отправляет данные TCP. Передаёт данные из строки в подключённый сокет, но пытается отправить все данные перед возвратом. Возвращает None при успехе, возбуждает исключение при неудаче.
s.recvfrom() Принимает UDP-данные, аналогично recv(), но возвращаемое значение — (data, address). Здесь data — строка, содержащая полученные данные, а address — адрес сокета, из которого были отправлены данные.
s.sendto() Отправляет UDP-данные, посылая данные в сокет. address — кортеж вида (ipaddr, port), задающий удалённый адрес. Возвращаемое значение — количество отправленных байт.
s.close() Закрывает сокет
s.getpeername() Возвращает удалённый адрес подключённого сокета. Возвращаемое значение обычно представляет собой кортеж (ipaddr, port).
s.getsockname() Возвращает собственный адрес сокета. Обычно кортеж (ipaddr, port)
s.setsockopt(level,optname,value) Устанавливает значение указанной опции сокета.
s.getsockopt(level,optname[.buflen]) Возвращает значение опции сокета.
s.settimeout(timeout) Устанавливает период тайм-аута для операций с сокетом. timeout — число с плавающей запятой в секундах. Значение None означает отсутствие периода тайм-аута. Обычно период тайм-аута следует устанавливать сразу после создания сокета, поскольку они могут использоваться для операций подключения (например, connect())
s.gettimeout() Возвращает текущее значение тайм-аута в секундах; если период тайм-аута не установлен, возвращает None.
s.fileno() Возвращает файловый дескриптор сокета.
s.setblocking(flag) Если flag имеет значение False, переводит сокет в неблокирующий режим; в противном случае переводит сокет в блокирующий режим (по умолчанию). В неблокирующем режиме, если recv() не находит данных или send() не может немедленно отправить данные, будет вызвано исключение socket.error.
s.makefile() Создаёт файл, связанный с этим сокетом

Простой пример

Server

Мы используем функциюsocketмодуля socket для создания объекта сокета. Объект сокета может настроить службу сокета, вызывая другие функции.

Теперь мы можем вызвать функциюbind(hostname, port), чтобы указатьпорт сервиса。

Затем мы вызываем методacceptобъекта сокета. Этот метод ожидает подключения клиента и возвращает объектconnection, указывающий, что он подключился к клиенту.

Полный код приведён ниже:

Пример

#!/usr/bin/python3
# Имя файла: server.py

# Импорт модулей socket, sys
import socket
import sys

# Создать объект сокета
serversocket = socket.socket(
            socket.AF_INET, socket.SOCK_STREAM)

# Получить имя локального хоста
host = socket.gethostname()

port = 9999

# Привязать к номеру порта
serversocket.bind((host, port))

# Задайте максимальное количество подключений; остальные помещаются в очередь
serversocket.listen(5)

while True:
    # Установите соединение с клиентом
    clientsocket,addr = serversocket.accept()      

    print("Адрес подключения: %s" % str(addr))
   
    msg='Добро пожаловать в Example Tutorial!'+ "\r\n"
    clientsocket.send(msg.encode('utf-8'))
    clientsocket.close()

Клиент

Далее давайте напишем простой пример клиента для подключения к сервису, созданному выше. Номер порта — 9999.

socket.connect(hostname, port )— метод открывает TCP-соединение с хостомhostnameportport. Подключитесь к сервису. После подключения мы можем получать данные от сервера. Не забудьте закрыть соединение после завершения операции.

Полный код приведён ниже:

Пример

#!/usr/bin/python3
# Имя файла: client.py

# Импорт модулей socket, sys
import socket
import sys

# Создать объект сокета
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Получить имя локального хоста
host = socket.gethostname()

# Установить номер порта
port = 9999

# Подключиться к сервису, указав хост и порт
s.connect((host, port))

# Принять данные меньше 1024 байт
msg = s.recv(1024)

s.close()

print (msg.decode('utf-8'))

Теперь откроем два терминала. В первом терминале запустите файл server.py:

$ python3 server.py

Во втором терминале запустите файл client.py:

$ python3 client.py 
欢迎访问Example!

На этом этапе, если мы снова откроем первый терминал, мы увидим следующий вывод информации:

连接地址: ('192.168.0.118', 33397)

Интернет-модули Python

Ниже перечислены некоторые важные модули для сетевого программирования на Python:

ПротоколФункция/НазначениеНомер портаМодуль Python
HTTPВеб-доступ80httplib, urllib, xmlrpclib
NNTPЧтение и публикация новостных статей, обычно известных как "посты"119nntplib
FTPПередача файлов20ftplib, urllib
SMTPОтправка электронной почты25smtplib
POP3Получение электронной почты110poplib
IMAP4Загрузка электронной почты143imaplib
TelnetКомандная строка23telnetlib
GopherПоиск информации70gopherlib, urllib

Для получения дополнительного контента, пожалуйста, обратитесь к официальному сайтуБиблиотека сокетов и модули Python。

Другие расширения