Клиент-серверные приложения

Сокеты. Создание клиента

Последнее обновление: 03.05.2023

Встроенный модуль socket в Python представляет функциональность для взаимодействия по сети. Этот модуль определяет низкоуровневый интерфейс для отправки и получения запросов в виде класса socket. И вне зависимости, что мы создаем - программу сервера или клиента, для отправки запросов нам надо создать объект сокета:

import socket

sock = socket.socket()

После окончания работы с сокетом его следует закрыть с помощью метода close()

import socket

client = socket.socket()

client.close()

Дальнейшие действия с сокетом зависят от того, какой именно сокет мы создаем - для сервера или для клиента. В данном случае мы рассмотрим создание простейшего клиента на сокетах Python.

Подключение к серверу

Для подключения к серверу применяется метод connect()

socket.connect(address)

В качестве параметра он получает адрес сервера. Адрес обычно представляется в виде кортежа

(host, port)

Первый элемент - хост в виде строки. Это может быть, например, IP-адрес в виде "127.0.0.1" или название локального хоста. Второй параметр - числовой номер порта. Порт представляет 2-х байтное значение от 0 до 65535. Например:

import socket
 
client = socket.socket()
# подключаемся по адресу www.python.org и порту 80
client.connect(("www.python.org", 80))

print("Connected...")

client.close()  # закрываем подключение

Здесь пытаемся подключиться по адресу "www.python.org" и порту 80. То есть фактически мы пытаемся подключиться к обычному веб-сайту www.python.org, который работает на порту 80 (обычно веб-сервер запускается на порту 80). После подключения просто выводим строку на консоль и закрывает сокет.

Взаимодействие с сервером

После установки соединения мы можем отправлять и получать данные от сервера. Для отправки данных применяется метод socket.send(), который в качестве параметра получает набор отправляемых данных.

socket.send(bytes)

Для получения данных у сокета применяется метод socket.recv()

bytes = socket.recv(bufsize[, flags])

В качестве обязательного параметра он принимает максимальный размер буфера в байтах, которые могут быть получены за раз от другого сокета. Размер буфера лучше делать кратным 2, например, 512, 1024 и т.д. Возвращаемое значение - набор байтов, полученых от другого сокета.

Например, отправим данные на сервер "www.python.org" и получим от него ответ:

import socket
 
client = socket.socket()
# подключаемся по адресу www.python.org и порту 80
client.connect(("www.python.org", 80))
# данные для отправки - стандартные заголовки протокола http
message = "GET / HTTP/1.1\r\nHost: www.python.org\r\nConnection: close\r\n\r\n"
print("Connecting...")
client.send(message.encode())       # отправляем данные серверу
data = client.recv(1024)            # получаем данные с сервера
print("Server sent: ", data.decode())    # выводим данные на консоль
client.close()                      # закрываем подключение

В данном случае отправляется строка со стандартными заголовками протокола HTTP, которые пониманиет веб-сайт. Формат запроса HTTP включает прежде всего линию запроса ("GET / HTTP/1.1\r\nHost: www.python.org), которая состоит из типа запроса, пути к запрошенному ресурсу и специфической версии протокола. То есть здесь в сообщении мы указываем, что отправляется запрос типа GET по пути "/" (то есть к корню сайта www.python.org"). При этом применяется протокол HTTP/1.1. Линия запроса должна завершаться двойным набором символов каретки и перевода строки \r\n.

Кроме того, запрос HTTP может содержать заголовки. Так, в данном случае отправляем заголовок "Host", который указывает на адрес хоста. В данном случае это "www.python.org:80". И также в данном случае отправляем заголовок "Connection", который имеет значение "close" - это значение предписывает серверу закрыть подключение.

Поскольку мы можем послать только байты, а не строки, то при отправке переводим строку в набор байтов. Для этого применяется метод encode(), который возвращает объект класса bytes

client.send(message.encode())

После отправки серверу сообщения пытаемся получить от него данные с помощью метода recv(). При этом буфер для получаемых данных будет иметь размер в 1024 байта. Результат метода - полученные данные. Однако сокет получает данные в виде набора байт (точнее объекта bytes). Чтобы их преобразовать в строку, применяется метод decode():

data = client.recv(1024)            # получаем данные с сервера
print("Server sent: ", data.decode())    # выводим данные на консоль

И если мы запустим данную программу на Python, то получим ответ напродобие следующего:

Connected...
Server sent:  HTTP/1.1 301 Moved Permanently
Connection: close
Content-Length: 0
Server: Varnish
Retry-After: 0
Location: https://www.python.org/
Accept-Ranges: bytes
Date: Tue, 02 May 2023 17:52:32 GMT
Via: 1.1 varnish
X-Served-By: cache-bma1653-BMA
X-Cache: HIT
X-Cache-Hits: 0
X-Timer: S1683049953.637569,VS0,VE0
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

Сервер также нам присылает строку в http-заголовками, которые указывают, что веб-сайт переехал на адрес https://www.python.org/.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850