Compare commits
No commits in common. "a33e02858195951b829302ea54af5587d2a35e9a" and "c3fba40f81566c2c7f6110f21ba5353a308d383e" have entirely different histories.
a33e028581
...
c3fba40f81
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,7 +0,0 @@
|
|||||||
.venv/
|
|
||||||
__pycache__/
|
|
||||||
*.pyc
|
|
||||||
.env
|
|
||||||
.idea/
|
|
||||||
.vscode/
|
|
||||||
|
|
||||||
141
README.md
141
README.md
@ -1,140 +1,3 @@
|
|||||||
# Лабораторная работа 3
|
# lab3
|
||||||
|
|
||||||
Тема: работа с сетевыми соединениями в Python.
|
Repository created through Gitea API for lab 3
|
||||||
|
|
||||||
В проекте реализованы простые примеры TCP, UDP, HTTP-запросов через `socket` и `requests`, а также пример запроса к API Gitea.
|
|
||||||
|
|
||||||
## Подготовка
|
|
||||||
|
|
||||||
Создать и активировать виртуальное окружение:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
python -m venv .venv
|
|
||||||
.\.venv\Scripts\Activate.ps1
|
|
||||||
```
|
|
||||||
|
|
||||||
Установить зависимости:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
pip install -r requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
## TCP
|
|
||||||
|
|
||||||
Сервер:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
python tcp_server.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Клиент:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
python tcp_client.py "hello server"
|
|
||||||
```
|
|
||||||
|
|
||||||
Чтобы остановить TCP-сервер:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
python tcp_client.py EXIT
|
|
||||||
```
|
|
||||||
|
|
||||||
TCP-сервер работает на порту `10000`. Он принимает сообщение, переводит его в верхний регистр и возвращает клиенту.
|
|
||||||
|
|
||||||
Фильтр Wireshark:
|
|
||||||
|
|
||||||
```text
|
|
||||||
tcp.port==10000
|
|
||||||
```
|
|
||||||
|
|
||||||
## UDP
|
|
||||||
|
|
||||||
Сервер:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
python udp_server.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Клиент:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
python udp_client.py "hello server"
|
|
||||||
```
|
|
||||||
|
|
||||||
Чтобы остановить UDP-сервер:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
python udp_client.py EXIT
|
|
||||||
```
|
|
||||||
|
|
||||||
UDP-сервер работает на порту `10001`. Он принимает сообщение, переворачивает строку и возвращает клиенту.
|
|
||||||
|
|
||||||
Фильтр Wireshark:
|
|
||||||
|
|
||||||
```text
|
|
||||||
udp.port==10001
|
|
||||||
```
|
|
||||||
|
|
||||||
## HTTP через socket
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
python http_socket_client.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Программа вручную открывает TCP-соединение с `vyatsu.ru` на порту `80`, отправляет HTTP-запрос и выводит часть ответа.
|
|
||||||
При проверке сервер вернул ответ `301 Moved Permanently`, потому что сайт перенаправляет запрос на HTTPS-версию.
|
|
||||||
|
|
||||||
Фильтр Wireshark:
|
|
||||||
|
|
||||||
```text
|
|
||||||
tcp.port==80
|
|
||||||
```
|
|
||||||
|
|
||||||
## HTTP через requests
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
python http_requests_client.py
|
|
||||||
```
|
|
||||||
|
|
||||||
`requests` сам формирует HTTP-запрос, обрабатывает ответ и предоставляет удобный объект `response`.
|
|
||||||
При проверке `requests` автоматически обработал перенаправление и получил итоговый статус `200`.
|
|
||||||
|
|
||||||
## Gitea API
|
|
||||||
|
|
||||||
Токен нельзя хранить в коде. Нужно создать файл `.env`:
|
|
||||||
|
|
||||||
```text
|
|
||||||
GITEA_TOKEN=ваш_токен
|
|
||||||
```
|
|
||||||
|
|
||||||
Файл `.env` добавлен в `.gitignore`, поэтому он не должен попасть в коммит.
|
|
||||||
|
|
||||||
Запуск:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
python gitea_api.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Программа выполняет запрос к:
|
|
||||||
|
|
||||||
```text
|
|
||||||
https://git.vyatsu.ru/api/v1/user
|
|
||||||
```
|
|
||||||
|
|
||||||
Для создания репозитория через API используется файл:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
python create_gitea_repo.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Скрипт создает публичный репозиторий `API_REPO`.
|
|
||||||
|
|
||||||
## Выводы
|
|
||||||
|
|
||||||
TCP устанавливает соединение перед передачей данных. В Wireshark можно увидеть трехстороннее рукопожатие: `SYN`, `SYN-ACK`, `ACK`. При завершении соединения видны пакеты `FIN` и `ACK`.
|
|
||||||
|
|
||||||
UDP не устанавливает соединение перед отправкой данных. В Wireshark видны отдельные UDP-пакеты без handshake и без подтверждений доставки.
|
|
||||||
|
|
||||||
При работе через `socket` HTTP-запрос нужно составлять вручную. В примере через `socket` виден ответ `301 Moved Permanently`. Библиотека `requests` делает больше действий автоматически: формирует заголовки, обрабатывает ответ и переходит по перенаправлению, поэтому итоговый ответ получился со статусом `200`.
|
|
||||||
|
|
||||||
Через API Gitea был выполнен запрос к данным пользователя и создан репозиторий `API_REPO`. Для этого использовался токен, который хранится в `.env` и не попадает в коммиты.
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
import requests
|
|
||||||
|
|
||||||
|
|
||||||
API_URL = "https://git.vyatsu.ru/api/v1"
|
|
||||||
REPO_NAME = "API_REPO"
|
|
||||||
|
|
||||||
|
|
||||||
def load_token() -> str:
|
|
||||||
token = os.getenv("GITEA_TOKEN")
|
|
||||||
if token:
|
|
||||||
return token
|
|
||||||
|
|
||||||
if os.path.exists(".env"):
|
|
||||||
with open(".env", "r", encoding="utf-8") as file:
|
|
||||||
for line in file:
|
|
||||||
line = line.strip()
|
|
||||||
if line.startswith("GITEA_TOKEN="):
|
|
||||||
return line.split("=", 1)[1].strip()
|
|
||||||
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
token = load_token()
|
|
||||||
if not token:
|
|
||||||
print("Token not found. Create .env file with GITEA_TOKEN=your_token")
|
|
||||||
raise SystemExit(1)
|
|
||||||
|
|
||||||
headers = {"Authorization": f"token {token}"}
|
|
||||||
data = {
|
|
||||||
"name": REPO_NAME,
|
|
||||||
"description": "Repository created through Gitea API for lab 3",
|
|
||||||
"private": False,
|
|
||||||
"auto_init": True,
|
|
||||||
}
|
|
||||||
|
|
||||||
response = requests.post(
|
|
||||||
f"{API_URL}/user/repos",
|
|
||||||
headers=headers,
|
|
||||||
json=data,
|
|
||||||
timeout=10,
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"Status code: {response.status_code}")
|
|
||||||
|
|
||||||
if response.status_code == 201:
|
|
||||||
repo = response.json()
|
|
||||||
print("Repository created")
|
|
||||||
print(f"Name: {repo.get('full_name')}")
|
|
||||||
print(f"URL: {repo.get('html_url')}")
|
|
||||||
elif response.status_code == 409:
|
|
||||||
print(f"Repository {REPO_NAME} already exists")
|
|
||||||
else:
|
|
||||||
print(response.text)
|
|
||||||
|
|
||||||
42
gitea_api.py
42
gitea_api.py
@ -1,42 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
import requests
|
|
||||||
|
|
||||||
|
|
||||||
API_URL = "https://git.vyatsu.ru/api/v1"
|
|
||||||
|
|
||||||
|
|
||||||
def load_token() -> str:
|
|
||||||
token = os.getenv("GITEA_TOKEN")
|
|
||||||
if token:
|
|
||||||
return token
|
|
||||||
|
|
||||||
if os.path.exists(".env"):
|
|
||||||
with open(".env", "r", encoding="utf-8") as file:
|
|
||||||
for line in file:
|
|
||||||
line = line.strip()
|
|
||||||
if line.startswith("GITEA_TOKEN="):
|
|
||||||
return line.split("=", 1)[1].strip()
|
|
||||||
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
token = load_token()
|
|
||||||
if not token:
|
|
||||||
print("Token not found. Create .env file with GITEA_TOKEN=your_token")
|
|
||||||
raise SystemExit(1)
|
|
||||||
|
|
||||||
headers = {"Authorization": f"token {token}"}
|
|
||||||
|
|
||||||
response = requests.get(f"{API_URL}/user", headers=headers, timeout=10)
|
|
||||||
print(f"Status code: {response.status_code}")
|
|
||||||
|
|
||||||
if response.ok:
|
|
||||||
user = response.json()
|
|
||||||
print("Gitea user information:")
|
|
||||||
print(f"Login: {user.get('login')}")
|
|
||||||
print(f"Full name: {user.get('full_name')}")
|
|
||||||
print(f"Email: {user.get('email')}")
|
|
||||||
else:
|
|
||||||
print(response.text)
|
|
||||||
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
import requests
|
|
||||||
|
|
||||||
|
|
||||||
response = requests.get("http://vyatsu.ru", timeout=10)
|
|
||||||
|
|
||||||
print(f"Status code: {response.status_code}")
|
|
||||||
print(response.text[:500])
|
|
||||||
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
import socket
|
|
||||||
|
|
||||||
|
|
||||||
HOST = "vyatsu.ru"
|
|
||||||
PORT = 80
|
|
||||||
|
|
||||||
|
|
||||||
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
||||||
client.connect((HOST, PORT))
|
|
||||||
|
|
||||||
request = (
|
|
||||||
"GET / HTTP/1.1\r\n"
|
|
||||||
"Host: vyatsu.ru\r\n"
|
|
||||||
"User-Agent: python-socket-lab3\r\n"
|
|
||||||
"Accept: text/html\r\n"
|
|
||||||
"Connection: close\r\n"
|
|
||||||
"\r\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
client.sendall(request.encode("utf-8"))
|
|
||||||
|
|
||||||
response_parts = []
|
|
||||||
while True:
|
|
||||||
data = client.recv(4096)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
response_parts.append(data)
|
|
||||||
|
|
||||||
client.close()
|
|
||||||
|
|
||||||
response = b"".join(response_parts)
|
|
||||||
print(response.decode("utf-8", errors="replace")[:2000])
|
|
||||||
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
requests
|
|
||||||
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
import socket
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
HOST = "127.0.0.1"
|
|
||||||
PORT = 10000
|
|
||||||
|
|
||||||
|
|
||||||
message = "hello server"
|
|
||||||
if len(sys.argv) > 1:
|
|
||||||
message = " ".join(sys.argv[1:])
|
|
||||||
|
|
||||||
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
||||||
client.connect((HOST, PORT))
|
|
||||||
client.sendall(message.encode("utf-8"))
|
|
||||||
|
|
||||||
data = client.recv(1024)
|
|
||||||
print(f"Response from server: {data.decode('utf-8')}")
|
|
||||||
|
|
||||||
client.close()
|
|
||||||
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
import socket
|
|
||||||
|
|
||||||
|
|
||||||
HOST = "0.0.0.0"
|
|
||||||
PORT = 10000
|
|
||||||
|
|
||||||
|
|
||||||
def process_message(message: str) -> str:
|
|
||||||
return f"TCP server received: {message.upper()}"
|
|
||||||
|
|
||||||
|
|
||||||
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
||||||
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
||||||
server.bind((HOST, PORT))
|
|
||||||
server.listen(1)
|
|
||||||
|
|
||||||
print(f"TCP server started on port {PORT}")
|
|
||||||
print("Send EXIT from client to stop the server")
|
|
||||||
|
|
||||||
while True:
|
|
||||||
conn, addr = server.accept()
|
|
||||||
print(f"Connection from {addr}")
|
|
||||||
|
|
||||||
data = conn.recv(1024)
|
|
||||||
if not data:
|
|
||||||
conn.close()
|
|
||||||
continue
|
|
||||||
|
|
||||||
message = data.decode("utf-8")
|
|
||||||
response = process_message(message)
|
|
||||||
conn.sendall(response.encode("utf-8"))
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
if message.strip().upper() == "EXIT":
|
|
||||||
print("TCP server stopped")
|
|
||||||
break
|
|
||||||
|
|
||||||
server.close()
|
|
||||||
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
import socket
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
HOST = "127.0.0.1"
|
|
||||||
PORT = 10001
|
|
||||||
|
|
||||||
|
|
||||||
message = "hello server"
|
|
||||||
if len(sys.argv) > 1:
|
|
||||||
message = " ".join(sys.argv[1:])
|
|
||||||
|
|
||||||
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
||||||
client.sendto(message.encode("utf-8"), (HOST, PORT))
|
|
||||||
|
|
||||||
data, _ = client.recvfrom(1024)
|
|
||||||
print(f"Response from server: {data.decode('utf-8')}")
|
|
||||||
|
|
||||||
client.close()
|
|
||||||
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
import socket
|
|
||||||
|
|
||||||
|
|
||||||
HOST = "0.0.0.0"
|
|
||||||
PORT = 10001
|
|
||||||
|
|
||||||
|
|
||||||
def process_message(message: str) -> str:
|
|
||||||
return f"UDP server received: {message[::-1]}"
|
|
||||||
|
|
||||||
|
|
||||||
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
||||||
server.bind((HOST, PORT))
|
|
||||||
|
|
||||||
print(f"UDP server started on port {PORT}")
|
|
||||||
print("Send EXIT from client to stop the server")
|
|
||||||
|
|
||||||
while True:
|
|
||||||
data, addr = server.recvfrom(1024)
|
|
||||||
message = data.decode("utf-8")
|
|
||||||
print(f"Message from {addr}: {message}")
|
|
||||||
|
|
||||||
response = process_message(message)
|
|
||||||
server.sendto(response.encode("utf-8"), addr)
|
|
||||||
|
|
||||||
if message.strip().upper() == "EXIT":
|
|
||||||
print("UDP server stopped")
|
|
||||||
break
|
|
||||||
|
|
||||||
server.close()
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user