def translate_message(response): """ Разбор сообщения :param response: Словарь ответа от сервера :return: корректный словарь ответа """ # Передали не словарь if not isinstance(response, dict): logger.error('С сервера был передан не словарь.') raise TypeError # Нету ключа response if RESPONSE not in response: # Ошибка нужен обязательный ключ logger.error('С сервера не пришёл ключ в response.') raise MandatoryKeyError(RESPONSE) # получаем код ответа code = response[RESPONSE] logger.debug(f'Получен код ответа: { code }') # длина кода не 3 символа if len(str(code)) != 3: # Ошибка неверная длина кода ошибки logger.error('Неверная длина кода ответа сервера.') raise ResponseCodeLenError(code) # неправильные коды символов if code not in RESPONSE_CODES: # ошибка неверный код ответа logger.error('Несуществующий код ответа сервера.') raise ResponseCodeError(code) # возвращаем ответ logger.debug(f'Возвращается ответ: { response }') return response
def create_presence(self): """ Формируем presence-сообщение :param account_name: Имя пользователя :return: Словарь сообщения tests: pytest """ # Если имя не строка if not isinstance(self.login, str): logger.error( f'Введённый account_name: { self.login } - не является строкой.' ) raise TypeError # Если длина имени пользователя больше 20 символов if len(self.login) >= 20: logger.error( f'Длина account_name: { self.login } - превышает разрешённую. Максимальная длина имени 20 символов.' ) raise UsernameToLongError(self.login) # Формируем словарь сообщения message = { ACTION: PRESENCE, TIME: time.time(), USER: { LOGIN: self.login, PASSWORD: self.password } } logger.debug('Формируем presence-message.') return message
def get_contacts(self): # Формируем словарь сообщения message = { ACTION: 'get_contacts', TIME: time.time(), } JimSend(self.sock).send_message(message) data = JimRcv(self.sock).get_message() # TODO: response = translate_message(response) logger.debug(f'Ответ сервера: { data }') print(data) for i in range(data['quantity']): response = JimRcv(self.sock).get_message() print(response) Actions(self.sock)
def read_requests(self): # Чтение запросов из списка клиентов responses = {} # Словарь ответов сервера вида {сокет: запрос} for sock in self.r: try: data = JimRcv(sock).get_message() logger.debug(f'Получили сообщение от клиента: {data}') # responses[sock] = data for sock2 in self.w: responses[sock2] = data logger.debug(f'Отпраляем словарь ответов сервера: {responses}') except: print('Клиент {} {} отключился'.format(sock.fileno(), sock.getpeername())) logger.info('Клиент {} {} отключился'.format( sock.fileno(), sock.getpeername())) self.clients.remove(sock) return responses
def choice(self): print('Нажмите -hepl, чтобы получить полный список команд.') reply = input() if reply[0] == '-': if reply[1:] == 'help': logger.debug('Пользователь. Список всех команд.') print('-w == писать сообщения, \n' '-r == читать сообщения, \n' '-add username == добавить в друзья username \n' '-del username == удалить из друзей username \n' '-get_contacts == получить список контактов, \n' '-exit == выйти') Client.choice(self) elif reply[1:] == 'w': logger.debug('Пользователь. Отправка сообщений.') Actions(self.sock).start_chat() elif reply[1:] == 'r': logger.debug('Пользователь. Получение сообщений.') Actions(self.sock).start_chat() elif reply[1:] == 'get_contacts': Actions(self.sock).get_contacts() elif reply[1:] == 'exit': raise ERROR elif 'add' in reply[1:]: pass elif 'del' in reply[1:]: pass else: print('Неверно введенная команда. Повторите попытку.') logger.debug('Неправльно введенные данные при выборе функции.') Client.choice(self) else: print('Неверно введенная команда. Повторите попытку.') logger.debug('Неправльно введенные данные при выборе функции.') Client.choice(self)
def connect(self): # Соединиться с сервером self.sock = socket(AF_INET, SOCK_STREAM) self.sock.connect(ADDRESS) # Создаем сообщение self.presence = self.create_presence() # Отсылаем сообщение logger.debug('Отправляем presence-message.') JimSend(self.sock).send_message(self.presence) # Получаем ответ logger.debug('Получаем ответ сервера.') response = JimRcv(self.sock).get_message() # Проверяем ответ logger.debug('Проверяем ответ сервера.') response = translate_message(response) logger.debug(f'Ответ сервера: {response}') return response
def write_responses(self): # Эхо-ответ сервера клиентам, от которых были запросы for sock in self.w: if sock in self.requests: try: if self.requests[sock][ACTION] == 'get_contacts': Server.get_contacts(self, sock) elif self.requests[sock][ACTION] == 'write': # Подготовить и отправить ответ сервера resp = { RESPONSE: 200, 'message': self.requests[sock]['message'] } JimSend(sock).send_message(resp) logger.debug( f'Отвера сервера был отправлен клинету {sock.fileno()} {sock.getpeername()}' ) except: # Сокет недоступен, клиент отключился print('Клиент {} {} отключился'.format( sock.fileno(), sock.getpeername())) logger.info('Клиент {} {} отключился'.format( sock.fileno(), sock.getpeername())) sock.close() self.clients.remove(sock)
def __init__(self): address = ('', 8888) try: addr = sys.argv[1] except IndexError: addr = '' try: port = int(sys.argv[2]) except IndexError: port = 8888 except ValueError: print('Порт должен быть целым числом') sys.exit(0) self.clients = [] self.s = socket(AF_INET, SOCK_STREAM) # TODO что такое bind, и зачем он нужен self.s.bind(address) self.s.listen(100) self.s.settimeout(0.2) # Таймаут для операций с сокетом while True: try: self.conn, self.addr = self.s.accept() # Проверка подключения logger.debug('Проверка подключения прошла успешно.') # Получаем сообщение от клиента self.presence = JimRcv(self.conn).get_message() logger.debug( f'Сообщение от клиента было получено: {self.presence}') # Формируем ответ response = Server.presence_response(self) logger.debug(f'Клинту был сформирован ответ: {response}') # Отправляем ответ клиенту JimSend(self.conn).send_message(response) logger.info(f'Клиенту был отправлен ответ: {response}') self.connect_to_db() # Выполним вход Server.login(self) sender = TimeServer(self.conn, 5) th_sender = Thread(target=sender) th_sender.start() except OSError as e: pass # timeout Вышел else: self.clients.append(self.conn) finally: # Проверяю наличие событий ввода-вывода self.wait = 0 self.r = [] self.w = [] try: self.r, self.w, self.e = select.select( self.clients, self.clients, [], self.wait) # print('r | ', self.r) # print('w | ', self.w) # r делают send # w делают read except: pass self.requests = Server.read_requests( self) # Сохраним запросы клиентов Server.write_responses( self) # Выполним отправку ответов клиентам