Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions lesson04/client/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/python3
__author__ = "Андрей Петров"

"""
клиент отправляет запрос серверу;
сервер отвечает соответствующим кодом результата. Клиент и сервер должны быть реализованы в виде отдельных скриптов,
содержащих соответствующие функции.

Функции клиента:
сформировать presence-сообщение;
отправить сообщение серверу;
получить ответ сервера;
разобрать сообщение сервера;
параметры командной строки скрипта client.py <addr> [<port>]: addr — ip-адрес сервера;
port — tcp-порт на сервере,
по умолчанию 7777.

"""
import re
import sys
import argparse
import socket
import json
from datetime import datetime


def createParser():
parser = argparse.ArgumentParser()
parser.add_argument('host', nargs='?', default='localhost')
parser.add_argument('port', nargs='?', default='7777')
return parser


parser = createParser()
args = parser.parse_args(sys.argv[1:])

port = int(re.search('[0-9]{2,}', args.port).group(0))

sock = socket.socket()
sock.connect((args.host, port))

# сформировать presence-сообщение;
# В формате JIM
msg_presence = json.dumps(
{
"action": "presence",
"time": datetime.now().timestamp(),
"type": "status",
"user": {
"account_name": "User Name",
"status": "Yep, I am here!"
}
}
)

msg_lower = json.dumps(
{
"action": "lower_text",
"data": 'GGGGG'
}
)

# отправить сообщение серверу;
sock.send(msg_presence.encode())
#sock.send(msg_lower.encode())

# получить ответ сервера;
data = sock.recv(1024)
response = json.loads(
data.decode('utf-8')
)
# разобрать сообщение сервера;
if response.get('response') == 200:
print(
f"Response Message: {response.get('msg')}"
)
else:
print(
f"Error: {response.get('error')}"
)
sock.close()
79 changes: 79 additions & 0 deletions lesson04/server/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/python3
__author__ = "Андрей Петров"

"""
клиент отправляет запрос серверу;
сервер отвечает соответствующим кодом результата. Клиент и сервер должны быть реализованы в виде отдельных скриптов,
содержащих соответствующие функции.

Функции сервера:
принимает сообщение клиента;
формирует ответ клиенту;
отправляет ответ клиенту;
имеет параметры командной строки: -p <port> — TCP-порт для работы (по умолчанию использует 7777);
-a <addr> — IP-адрес для прослушивания (по умолчанию слушает все доступные адреса).
"""

import sys
import os
import json
import socket
import argparse
from routes import get_server_routes


def createParser():
parser = argparse.ArgumentParser()
parser.add_argument('-a', '--addr', nargs='?', default='')
parser.add_argument('-p', '--port', nargs='?', default='7777')
return parser


parser = createParser()
args = parser.parse_args(sys.argv[1:])


sock = socket.socket()
sock.bind((args.addr, int(args.port)))
sock.listen(5)


## Без этого не работал код из урока
os.chdir('server')
sys.path.append(os.getcwd())
##

while True:
# принимает сообщение клиента;
client, address = sock.accept()

data = client.recv(1024)
request = json.loads(
data.decode('utf-8')
)

# формирует ответ клиенту;

client_action = request.get('action')

resolved_routes = list(
filter(
lambda itm: itm.get('action') == client_action,
get_server_routes()
)
)

route = resolved_routes[0] if resolved_routes else None
if route:
controller = route.get('controller')
response = controller(request)

else:
response = {
"response": 400,
"error": "Wrong action, try again"
}

# отправляет ответ клиенту;
client.send(json.dumps(response).encode('utf-8'))
client.close()
20 changes: 20 additions & 0 deletions lesson04/server/routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import os
from importlib import import_module
from functools import reduce


def get_server_routes():
return reduce(
lambda routes, module: routes + getattr(module, 'routes', []),
reduce(
lambda modules, dir: modules + [import_module(f'{dir}.routes')],
filter(
lambda itm: os.path.isdir(itm) and itm != '__pycache__' and itm != '.pytest_cache',
os.listdir()
),
[]
),
[]
)


5 changes: 5 additions & 0 deletions lesson04/server/test_module/controllers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def send_presence(request):
return {
"response": 200,
"msg": f"Hi {request.get('user')['account_name']}"
}
6 changes: 6 additions & 0 deletions lesson04/server/test_module/routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .controllers import send_presence


routes = [
{'action': 'presence', 'controller': send_presence}
]
22 changes: 22 additions & 0 deletions lesson04/tests/test_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import sys
sys.path.append('../')

from server.test_module.controllers import send_presence

REQUEST = {
"action": "presence",
"type": "status",
"user": {
"account_name": "User Name",
"status": "Yep, I am here!"
}
}

RESPONSE = {
"response": 200,
"msg": "Hi User Name"
}


def presence_msg_request_to_response():
assert send_presence(REQUEST) == RESPONSE