From 6982dcaf4ed1f182b1157b08885dd3afe1d254e5 Mon Sep 17 00:00:00 2001 From: impreza555 Date: Thu, 17 Mar 2022 17:23:30 +0300 Subject: [PATCH 1/4] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=94=D0=97.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- messenger/__init__.py | 0 messenger/client.py | 52 ++++++++++++++++++++++++++++++++ messenger/common/__init__.py | 0 messenger/common/settings.py | 26 ++++++++++++++++ messenger/common/utilites.py | 35 ++++++++++++++++++++++ messenger/server.py | 58 ++++++++++++++++++++++++++++++++++++ 6 files changed, 171 insertions(+) create mode 100644 messenger/__init__.py create mode 100644 messenger/client.py create mode 100644 messenger/common/__init__.py create mode 100644 messenger/common/settings.py create mode 100644 messenger/common/utilites.py create mode 100644 messenger/server.py diff --git a/messenger/__init__.py b/messenger/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/messenger/client.py b/messenger/client.py new file mode 100644 index 0000000..25c7a40 --- /dev/null +++ b/messenger/client.py @@ -0,0 +1,52 @@ +from sys import argv +from json import JSONDecodeError +import socket +import time +from common.settings import ACTION, PRESENCE, TIME, USER, ACCOUNT_NAME, RESPONSE, ERROR, DEFAULT_IP_ADDRESS, DEFAULT_PORT +from common.utilites import Message + + +class Client: + def presence(self, account_name='Guest'): + out = { + ACTION: PRESENCE, + TIME: time.time(), + USER: { + ACCOUNT_NAME: account_name + } + } + return out + + def response(self, message): + if RESPONSE in message: + if message[RESPONSE] == 200: + return 'Соединение установлено' + return f'Ошибка соединения с сервером: {message[ERROR]}' + + def start(self, account_name='Guest'): + try: + address = argv[1] + port = int(argv[2]) + if 1024 > port > 65535: + raise ValueError + except IndexError: + address = DEFAULT_IP_ADDRESS + port = DEFAULT_PORT + except ValueError: + print('Порт может быть в диапазоне от 1024 до 65535.') + exit(1) + + transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + transport.connect((address, port)) + message_to_server = self.presence(account_name) + Message.send(transport, message_to_server) + try: + answer = self.response(Message.get(transport)) + print(answer) + except (ValueError, JSONDecodeError): + print('Ошибка декодирования сообщения.') + + +if __name__ == '__main__': + client = Client() + client.start('Вася Пупкин') diff --git a/messenger/common/__init__.py b/messenger/common/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/messenger/common/settings.py b/messenger/common/settings.py new file mode 100644 index 0000000..cf2ada6 --- /dev/null +++ b/messenger/common/settings.py @@ -0,0 +1,26 @@ +# Порт по умолчанию для сетевого ваимодействия +DEFAULT_PORT = 7777 + +# IP адрес по умолчанию для подключения клиента +DEFAULT_IP_ADDRESS = '127.0.0.1' + +# Максимальная очередь подключений +MAX_CONNECTIONS = 5 + +# Максимальная длинна сообщения в байтах +MAX_PACKAGE_LENGTH = 1024 + +# Кодировка проекта +ENCODING = 'utf-8' + +# Прококол JIM основные ключи: +ACTION = 'action' +TIME = 'time' +USER = 'user' +ACCOUNT_NAME = 'account_name' + +# Прочие ключи, используемые в протоколе +PRESENCE = 'presence' +RESPONSE = 'response' +ERROR = 'error' +RESPONDEFAULT_IP_ADDRESSSE = 'respondefault_ip_addressse' diff --git a/messenger/common/utilites.py b/messenger/common/utilites.py new file mode 100644 index 0000000..388e1de --- /dev/null +++ b/messenger/common/utilites.py @@ -0,0 +1,35 @@ +import json +from common.settings import MAX_PACKAGE_LENGTH, ENCODING + + +class Encoder: + @staticmethod + def encoding(data): + if isinstance(data, dict): + return json.dumps(data).encode(ENCODING) + else: + raise ValueError('Данные должны быть словарем') + + @staticmethod + def decoding(data): + if isinstance(data, bytes): + msg = json.loads(data.decode(ENCODING)) + if isinstance(msg, dict): + return msg + else: + raise ValueError('Данные должны быть словарем') + else: + raise ValueError('Данные должны быть байтами') + + +class Message: + @staticmethod + def get(client): + response = client.recv(MAX_PACKAGE_LENGTH) + encoded_response = Encoder.decoding(response) + return encoded_response + + @staticmethod + def send(sock, message): + encoded_message = Encoder.encoding(message) + sock.send(encoded_message) diff --git a/messenger/server.py b/messenger/server.py new file mode 100644 index 0000000..8ee8311 --- /dev/null +++ b/messenger/server.py @@ -0,0 +1,58 @@ +import socket +from sys import argv +from json import JSONDecodeError +from common.settings import ACTION, RESPONSE, MAX_CONNECTIONS, PRESENCE, TIME, USER, ERROR, DEFAULT_PORT, RESPONDEFAULT_IP_ADDRESSSE +from common.utilites import Message + + +class Server: + def process(self, message): + if ACTION in message and message[ACTION] == PRESENCE and TIME in message and USER in message: + return {RESPONSE: 200} + return { + RESPONDEFAULT_IP_ADDRESSSE: 400, + ERROR: 'Bad Request' + } + + def start(self): + try: + if '-p' in argv: + port = int(argv[argv.index('-p') + 1]) + else: + port = DEFAULT_PORT + if 1024 > port > 65535: + raise ValueError + except IndexError: + print('После параметра -\'p\' необходимо указать номер порта.') + exit(1) + except ValueError: + print('Порт может быть в диапазоне от 1024 до 65535.') + exit(1) + try: + if '-a' in argv: + address = argv[argv.index('-a') + 1] + else: + address = '' + except IndexError: + print( + 'После параметра \'a\'- необходимо указать адрес, который будет слушать сервер.') + exit(1) + transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + transport.bind((address, port)) + transport.listen(MAX_CONNECTIONS) + while True: + client, address = transport.accept() + try: + message_from_cient = Message.get(client) + print(message_from_cient) + response = self.process(message_from_cient) + Message.send(client, response) + client.close() + except (ValueError, JSONDecodeError): + print('Ошибка декодирования сообщения.') + client.close() + + +if __name__ == '__main__': + server = Server() + server.start() From b96913e66505558dc12ead21529b0fcb5facda2b Mon Sep 17 00:00:00 2001 From: impreza555 Date: Thu, 17 Mar 2022 17:25:02 +0300 Subject: [PATCH 2/4] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=94=D0=97.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 62c8935..a047a94 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.idea/ \ No newline at end of file +.idea/ +__pycache__/ \ No newline at end of file From 1e882053e3f995bf428cd39d83396a8297c788ff Mon Sep 17 00:00:00 2001 From: impreza555 Date: Fri, 25 Mar 2022 22:44:49 +0300 Subject: [PATCH 3/4] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=94=D0=97.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- messenger/Tests/__init__.py | 0 messenger/Tests/test_client.py | 30 ++++++++++++++++ messenger/Tests/test_server.py | 43 ++++++++++++++++++++++ messenger/Tests/test_utilites.py | 61 ++++++++++++++++++++++++++++++++ messenger/client.py | 30 +++++++++++----- messenger/common/utilites.py | 6 ++-- messenger/server.py | 27 +++++++------- 7 files changed, 172 insertions(+), 25 deletions(-) create mode 100644 messenger/Tests/__init__.py create mode 100644 messenger/Tests/test_client.py create mode 100644 messenger/Tests/test_server.py create mode 100644 messenger/Tests/test_utilites.py diff --git a/messenger/Tests/__init__.py b/messenger/Tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/messenger/Tests/test_client.py b/messenger/Tests/test_client.py new file mode 100644 index 0000000..3b32543 --- /dev/null +++ b/messenger/Tests/test_client.py @@ -0,0 +1,30 @@ +import os +import sys +import unittest + +sys.path.append(os.path.join(os.getcwd(), '..')) +from common.settings import RESPONSE, ERROR, USER, ACCOUNT_NAME, TIME, ACTION, PRESENCE +from client import Client + + +class TestClass(unittest.TestCase): + def setUp(self): + self.client = Client() + + def test_def_presense(self): + test = self.client.presence() + test[TIME] = 5.2 + self.assertEqual(test, {ACTION: PRESENCE, TIME: 5.2, USER: {ACCOUNT_NAME: 'Guest'}}) + + def test_200_ans(self): + self.assertEqual(self.client.response({RESPONSE: 200}), 'Соединение установлено') + + def test_400_ans(self): + self.assertEqual(self.client.response({RESPONSE: 400, ERROR: 'Bad Request'}), 'Ошибка соединения с сервером: Bad Request') + + def test_no_response(self): + self.assertRaises(ValueError, self.client.response, {ERROR: 'Bad Request'}) + + +if __name__ == '__main__': + unittest.main() diff --git a/messenger/Tests/test_server.py b/messenger/Tests/test_server.py new file mode 100644 index 0000000..9ed5e27 --- /dev/null +++ b/messenger/Tests/test_server.py @@ -0,0 +1,43 @@ +import os +import sys +import unittest + +sys.path.append(os.path.join(os.getcwd(), '..')) +from common.settings import RESPONSE, ERROR, USER, ACCOUNT_NAME, TIME, ACTION, PRESENCE +from server import Server + + +class TestServer(unittest.TestCase): + err_dict = { + RESPONSE: 400, + ERROR: 'Bad Request' + } + ok_dict = {RESPONSE: 200} + + def setUp(self): + self.server = Server() + + def test_ok_check(self): + self.assertEqual(self.server.process({ACTION: PRESENCE, TIME: 1.1, USER: {ACCOUNT_NAME: 'Guest'}}), + self.ok_dict) + + def test_no_action(self): + self.assertEqual(self.server.process({TIME: '1.1', USER: {ACCOUNT_NAME: 'Guest'}}), self.err_dict) + + def test_wrong_action(self): + self.assertEqual(self.server.process({ACTION: 'Wrong', TIME: '1.1', USER: {ACCOUNT_NAME: 'Guest'}}), + self.err_dict) + + def test_no_time(self): + self.assertEqual(self.server.process({ACTION: PRESENCE, USER: {ACCOUNT_NAME: 'Guest'}}), self.err_dict) + + def test_no_user(self): + self.assertEqual(self.server.process({ACTION: PRESENCE, TIME: '1.1'}), self.err_dict) + + def test_unknown_user(self): + self.assertEqual(self.server.process({ACTION: PRESENCE, TIME: 1.1, USER: {ACCOUNT_NAME: 'Guest_1'}}), + self.err_dict) + + +if __name__ == '__main__': + unittest.main() diff --git a/messenger/Tests/test_utilites.py b/messenger/Tests/test_utilites.py new file mode 100644 index 0000000..7a250ef --- /dev/null +++ b/messenger/Tests/test_utilites.py @@ -0,0 +1,61 @@ +import os +import sys +import unittest + +sys.path.append(os.path.join(os.getcwd(), '..')) +from common.settings import USER, ACCOUNT_NAME, TIME, ACTION, PRESENCE +from common.utilites import Encoder, Message + +test_dict_send = { + ACTION: PRESENCE, + TIME: 111111.111111, + USER: { + ACCOUNT_NAME: 'test_test' + } +} +test_dict_encoded = b'{"action": "presence", "time": 111111.111111, "user": {"account_name": "test_test"}}' + + +class TestSocket: + def __init__(self, test_dict, dict_encoded): + self.test_dict = test_dict + self.dict_encoded = dict_encoded + self.received_message = None + + def send(self, message_to_send): + self.received_message = message_to_send + return self.received_message + + def recv(self, max_len): + self.max_len = max_len + return self.dict_encoded + + +class TestUtilites(unittest.TestCase): + def setUp(self): + self.encoder = Encoder() + self.message = Message() + self.test_socket = TestSocket(test_dict_send, test_dict_encoded) + + def test_encode_message(self): + self.assertEqual(self.encoder.encoding(test_dict_send), test_dict_encoded) + + def test_encode_error_value(self): + self.assertRaises(ValueError, self.encoder.encoding, 'non_dict_data') + + def test_decode_message(self): + self.assertEqual(self.encoder.decoding(test_dict_encoded), test_dict_send) + + def test_decode_error_json_loads(self): + self.assertRaises(ValueError, self.encoder.encoding, 'non_byte_data') + + def test_get_message(self): + self.assertEqual(self.message.get(self.test_socket), test_dict_send) + + def test_send_message(self): + self.message.send(self.test_socket, test_dict_send) + self.assertEqual(self.test_socket.received_message, test_dict_encoded) + + +if __name__ == '__main__': + unittest.main() diff --git a/messenger/client.py b/messenger/client.py index 25c7a40..387e4e3 100644 --- a/messenger/client.py +++ b/messenger/client.py @@ -1,8 +1,10 @@ -from sys import argv -from json import JSONDecodeError import socket import time -from common.settings import ACTION, PRESENCE, TIME, USER, ACCOUNT_NAME, RESPONSE, ERROR, DEFAULT_IP_ADDRESS, DEFAULT_PORT +from json import JSONDecodeError +from sys import argv + +from common.settings import ACTION, PRESENCE, TIME, USER, ACCOUNT_NAME, RESPONSE, ERROR, DEFAULT_IP_ADDRESS, \ + DEFAULT_PORT from common.utilites import Message @@ -22,20 +24,30 @@ def response(self, message): if message[RESPONSE] == 200: return 'Соединение установлено' return f'Ошибка соединения с сервером: {message[ERROR]}' + raise ValueError def start(self, account_name='Guest'): try: - address = argv[1] - port = int(argv[2]) + if '-a' in argv: + address = argv[argv.index('-a') + 1] + else: + address = DEFAULT_IP_ADDRESS + except IndexError: + print('После параметра \'a\'- необходимо указать адрес, к которому будет подключаться клиент.') + exit(1) + try: + if '-p' in argv: + port = int(argv[argv.index('-p') + 1]) + else: + port = DEFAULT_PORT if 1024 > port > 65535: raise ValueError except IndexError: - address = DEFAULT_IP_ADDRESS - port = DEFAULT_PORT + print('После параметра -\'p\' необходимо указать номер порта.') + exit(1) except ValueError: print('Порт может быть в диапазоне от 1024 до 65535.') exit(1) - transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM) transport.connect((address, port)) message_to_server = self.presence(account_name) @@ -49,4 +61,4 @@ def start(self, account_name='Guest'): if __name__ == '__main__': client = Client() - client.start('Вася Пупкин') + client.start() diff --git a/messenger/common/utilites.py b/messenger/common/utilites.py index 388e1de..7a13d45 100644 --- a/messenger/common/utilites.py +++ b/messenger/common/utilites.py @@ -25,9 +25,9 @@ def decoding(data): class Message: @staticmethod def get(client): - response = client.recv(MAX_PACKAGE_LENGTH) - encoded_response = Encoder.decoding(response) - return encoded_response + encoded_response = client.recv(MAX_PACKAGE_LENGTH) + response = Encoder.decoding(encoded_response) + return response @staticmethod def send(sock, message): diff --git a/messenger/server.py b/messenger/server.py index 8ee8311..91053f7 100644 --- a/messenger/server.py +++ b/messenger/server.py @@ -1,20 +1,30 @@ import socket -from sys import argv from json import JSONDecodeError -from common.settings import ACTION, RESPONSE, MAX_CONNECTIONS, PRESENCE, TIME, USER, ERROR, DEFAULT_PORT, RESPONDEFAULT_IP_ADDRESSSE +from sys import argv + +from common.settings import ACTION, RESPONSE, MAX_CONNECTIONS, PRESENCE, TIME, USER, ACCOUNT_NAME, ERROR, DEFAULT_PORT from common.utilites import Message class Server: def process(self, message): - if ACTION in message and message[ACTION] == PRESENCE and TIME in message and USER in message: + if ACTION in message and message[ACTION] == PRESENCE and TIME in message and USER in message \ + and message[USER][ACCOUNT_NAME] == 'Guest': return {RESPONSE: 200} return { - RESPONDEFAULT_IP_ADDRESSSE: 400, + RESPONSE: 400, ERROR: 'Bad Request' } def start(self): + try: + if '-a' in argv: + address = argv[argv.index('-a') + 1] + else: + address = '' + except IndexError: + print('После параметра \'a\'- необходимо указать адрес, который будет слушать сервер.') + exit(1) try: if '-p' in argv: port = int(argv[argv.index('-p') + 1]) @@ -28,15 +38,6 @@ def start(self): except ValueError: print('Порт может быть в диапазоне от 1024 до 65535.') exit(1) - try: - if '-a' in argv: - address = argv[argv.index('-a') + 1] - else: - address = '' - except IndexError: - print( - 'После параметра \'a\'- необходимо указать адрес, который будет слушать сервер.') - exit(1) transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM) transport.bind((address, port)) transport.listen(MAX_CONNECTIONS) From fb67997a20ccf05d5b23970de6e63978fbc3ad87 Mon Sep 17 00:00:00 2001 From: impreza555 Date: Sun, 27 Mar 2022 17:29:15 +0300 Subject: [PATCH 4/4] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=94=D0=97.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- messenger/client.py | 25 ++++++++++++++++++++----- messenger/common/settings.py | 7 ++++++- messenger/log/__init__.py | 0 messenger/log/client_log_config.py | 26 ++++++++++++++++++++++++++ messenger/log/server_log_config.py | 27 +++++++++++++++++++++++++++ messenger/server.py | 26 +++++++++++++++++++++----- 6 files changed, 100 insertions(+), 11 deletions(-) create mode 100644 messenger/log/__init__.py create mode 100644 messenger/log/client_log_config.py create mode 100644 messenger/log/server_log_config.py diff --git a/messenger/client.py b/messenger/client.py index 387e4e3..7159599 100644 --- a/messenger/client.py +++ b/messenger/client.py @@ -1,5 +1,7 @@ import socket import time +import logging +from log import client_log_config from json import JSONDecodeError from sys import argv @@ -8,6 +10,9 @@ from common.utilites import Message +CLIENT_LOGGER = logging.getLogger('client') + + class Client: def presence(self, account_name='Guest'): out = { @@ -17,15 +22,19 @@ def presence(self, account_name='Guest'): ACCOUNT_NAME: account_name } } + CLIENT_LOGGER.debug(f'Сформировано {PRESENCE} сообщение для пользователя {account_name}') return out def response(self, message): + CLIENT_LOGGER.debug(f'Разбор сообщения {message} от сервера') if RESPONSE in message: if message[RESPONSE] == 200: return 'Соединение установлено' return f'Ошибка соединения с сервером: {message[ERROR]}' + CLIENT_LOGGER.error('Неверный формат сообщения от сервера') raise ValueError + def start(self, account_name='Guest'): try: if '-a' in argv: @@ -33,7 +42,7 @@ def start(self, account_name='Guest'): else: address = DEFAULT_IP_ADDRESS except IndexError: - print('После параметра \'a\'- необходимо указать адрес, к которому будет подключаться клиент.') + CLIENT_LOGGER.critical('После параметра \'a\'- необходимо указать адрес, к которому будет подключаться клиент.') exit(1) try: if '-p' in argv: @@ -43,20 +52,26 @@ def start(self, account_name='Guest'): if 1024 > port > 65535: raise ValueError except IndexError: - print('После параметра -\'p\' необходимо указать номер порта.') + CLIENT_LOGGER.critical('После параметра -\'p\' необходимо указать номер порта.') exit(1) except ValueError: - print('Порт может быть в диапазоне от 1024 до 65535.') + CLIENT_LOGGER.critical('Порт может быть в диапазоне от 1024 до 65535.') exit(1) transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - transport.connect((address, port)) + try: + CLIENT_LOGGER.info(f'Подключение к серверу {address}:{port}') + transport.connect((address, port)) + except ConnectionRefusedError: + CLIENT_LOGGER.critical(f'Сервер не запущен на адресе {address}:{port}') + exit(1) message_to_server = self.presence(account_name) + CLIENT_LOGGER.debug(f'Сформировано сообщение для отправки на сервер: {message_to_server}') Message.send(transport, message_to_server) try: answer = self.response(Message.get(transport)) print(answer) except (ValueError, JSONDecodeError): - print('Ошибка декодирования сообщения.') + CLIENT_LOGGER.error('Ошибка декодирования сообщения.') if __name__ == '__main__': diff --git a/messenger/common/settings.py b/messenger/common/settings.py index cf2ada6..8db9ff9 100644 --- a/messenger/common/settings.py +++ b/messenger/common/settings.py @@ -1,3 +1,6 @@ +"""Здесь производятся настройки приложения""" +import logging + # Порт по умолчанию для сетевого ваимодействия DEFAULT_PORT = 7777 @@ -13,6 +16,9 @@ # Кодировка проекта ENCODING = 'utf-8' +# Текущий уровень логирования +LOGGING_LEVEL = logging.DEBUG + # Прококол JIM основные ключи: ACTION = 'action' TIME = 'time' @@ -23,4 +29,3 @@ PRESENCE = 'presence' RESPONSE = 'response' ERROR = 'error' -RESPONDEFAULT_IP_ADDRESSSE = 'respondefault_ip_addressse' diff --git a/messenger/log/__init__.py b/messenger/log/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/messenger/log/client_log_config.py b/messenger/log/client_log_config.py new file mode 100644 index 0000000..a4d677b --- /dev/null +++ b/messenger/log/client_log_config.py @@ -0,0 +1,26 @@ +import sys +import os +import logging +from common.settings import LOGGING_LEVEL +sys.path.append('../') + + +CLIENT_FORMATTER = logging.Formatter('%(asctime)s %(levelname)s %(filename)s %(message)s') +PATH = os.path.dirname(os.path.abspath(__file__)) +PATH = os.path.join(PATH, 'client.log') +STREAM_HANDLER = logging.StreamHandler(sys.stderr) +STREAM_HANDLER.setFormatter(CLIENT_FORMATTER) +STREAM_HANDLER.setLevel(logging.ERROR) +LOG_FILE = logging.FileHandler(PATH, encoding='utf8') +LOG_FILE.setFormatter(CLIENT_FORMATTER) +LOGGER = logging.getLogger('client') +LOGGER.addHandler(STREAM_HANDLER) +LOGGER.addHandler(LOG_FILE) +LOGGER.setLevel(LOGGING_LEVEL) + + +if __name__ == '__main__': + LOGGER.critical('Критическая ошибка') + LOGGER.error('Ошибка') + LOGGER.debug('Отладочная информация') + LOGGER.info('Информационное сообщение') diff --git a/messenger/log/server_log_config.py b/messenger/log/server_log_config.py new file mode 100644 index 0000000..7100972 --- /dev/null +++ b/messenger/log/server_log_config.py @@ -0,0 +1,27 @@ +import sys +import os +# import logging +import logging.handlers +from common.settings import LOGGING_LEVEL +sys.path.append('../') + + +SERVER_FORMATTER = logging.Formatter('%(asctime)s %(levelname)s %(filename)s %(message)s') +PATH = os.path.dirname(os.path.abspath(__file__)) +PATH = os.path.join(PATH, 'server.log') +STREAM_HANDLER = logging.StreamHandler(sys.stderr) +STREAM_HANDLER.setFormatter(SERVER_FORMATTER) +STREAM_HANDLER.setLevel(logging.ERROR) +LOG_FILE = logging.handlers.TimedRotatingFileHandler(PATH, encoding='utf8', interval=1, when='D') +LOG_FILE.setFormatter(SERVER_FORMATTER) +LOGGER = logging.getLogger('server') +LOGGER.addHandler(STREAM_HANDLER) +LOGGER.addHandler(LOG_FILE) +LOGGER.setLevel(LOGGING_LEVEL) + + +if __name__ == '__main__': + LOGGER.critical('Критическая ошибка') + LOGGER.error('Ошибка') + LOGGER.debug('Отладочная информация') + LOGGER.info('Информационное сообщение') \ No newline at end of file diff --git a/messenger/server.py b/messenger/server.py index 91053f7..64d533e 100644 --- a/messenger/server.py +++ b/messenger/server.py @@ -1,13 +1,19 @@ import socket from json import JSONDecodeError from sys import argv +import logging +from log import server_log_config from common.settings import ACTION, RESPONSE, MAX_CONNECTIONS, PRESENCE, TIME, USER, ACCOUNT_NAME, ERROR, DEFAULT_PORT from common.utilites import Message +SERVER_LOGGER = logging.getLogger('server') + + class Server: def process(self, message): + SERVER_LOGGER.debug(f'Разбор сообщения {message} от клиента') if ACTION in message and message[ACTION] == PRESENCE and TIME in message and USER in message \ and message[USER][ACCOUNT_NAME] == 'Guest': return {RESPONSE: 200} @@ -23,7 +29,7 @@ def start(self): else: address = '' except IndexError: - print('После параметра \'a\'- необходимо указать адрес, который будет слушать сервер.') + SERVER_LOGGER.critical('После параметра \'a\'- необходимо указать адрес, который будет слушать сервер.') exit(1) try: if '-p' in argv: @@ -33,24 +39,34 @@ def start(self): if 1024 > port > 65535: raise ValueError except IndexError: - print('После параметра -\'p\' необходимо указать номер порта.') + SERVER_LOGGER.critical('После параметра -\'p\' необходимо указать номер порта.') exit(1) except ValueError: - print('Порт может быть в диапазоне от 1024 до 65535.') + SERVER_LOGGER.critical('Порт может быть в диапазоне от 1024 до 65535.') exit(1) + SERVER_LOGGER.info(f'Запущен сервер: ' + f'Адрес(а) с которого(ых) принимаются подключения: {"Все" if not address else address}, ' + f'Порт для подключений: {port}') transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM) transport.bind((address, port)) + SERVER_LOGGER.info(f'Сервер начал прослушивание на адресе(ах): ' + f'{"Все" if not address else address}, ' + f'Порт для подключений: {port}') transport.listen(MAX_CONNECTIONS) while True: client, address = transport.accept() + SERVER_LOGGER.info(f'Установлено соедение с клиентом {address}') try: message_from_cient = Message.get(client) + SERVER_LOGGER.debug(f'Получено сообщение {message_from_cient}') print(message_from_cient) response = self.process(message_from_cient) + SERVER_LOGGER.debug(f'Cформирован ответ клиенту {response}') Message.send(client, response) + SERVER_LOGGER.debug(f'Отправлен ответ {response}, cоединение с клиентом {address} закрывается.') client.close() - except (ValueError, JSONDecodeError): - print('Ошибка декодирования сообщения.') + except JSONDecodeError: + SERVER_LOGGER.error(f'Ошибка декодирования сообщения от клиента {address}.') client.close()