def user_controls_cmd(sock, user_name): """ Обработчик поступающих команд от клиента :param sock: клиентский сокет :param user_name: имя текущего клиента :return: """ print( 'Команда \'message\' для ввода и отправки сообщения, \'exit\' для завершения работы: ' ) while True: command = input( 'Введите команду (m - написать сообщение, q - закрыть): ') if command == 'm': create_client_msg(sock, user_name) elif command == 'q': send_message(sock, create_exit_message(user_name)) CLIENT_LOGGER.info('Завершение работы по команде пользователя') print('*** Завершение работы ***') time.sleep(0.5) break else: print( 'Команда не распознана, попробуйте снова. \n' 'Команда \'message\' для ввода и отправки сообщения, \'exit\' для завершения работы: ' )
def main(): client = socket(AF_INET, SOCK_STREAM) try: addr = sys.argv[1] except IndexError: CLIENT_LOGGER.warning("Нет адреса сервера") addr = 'localhost' try: port = int(sys.argv[2]) except IndexError: CLIENT_LOGGER.warning("Выбран стандарный порт: 7777") port = 7777 except ValueError: CLIENT_LOGGER.error("Порт должен быть целым числом") client.close() sys.exit(0) CLIENT_LOGGER.debug("1. Соединение") client.connect((addr, port)) message = create_presence() CLIENT_LOGGER.debug("2. Отправка сообщения") send_message(client, message) CLIENT_LOGGER.debug("3. Ожидание ответа") response = get_message(client) response = translate_message(response) print(response) CLIENT_LOGGER.info('Response: ' + str(response)) client.close()
def create_client_msg(sock, account_name): """ Формирование и отправка на сервер сообщения клиента :param sock: клиентский сокет :param account_name: строка псевдонима :return message_dict: словарь сообщения клиента """ receiver_name = input('Введите получателя сообщения: ') message_str = input('Введите сообщение для отправки: ') message_dict = { ACTION: MESSAGE, TIME: time.time(), FROM: account_name, TO: receiver_name, MESSAGE_TEXT: message_str } CLIENT_LOGGER.debug(f'Сформировано сообщение: {message_dict}') try: send_message(sock, message_dict) CLIENT_LOGGER.info( f'Отправлено сообщение для пользователя {receiver_name}') except Exception: CLIENT_LOGGER.critical('Потеряно соединение с сервером.') sys.exit(1)
def main(): global server global client server = socket(AF_INET, SOCK_STREAM) try: addr = sys.argv[1] except IndexError: addr = '0.0.0.0' try: port = int(sys.argv[2]) except IndexError: port = 7777 except ValueError: print('Введите целое число') sys.exit(0) # a.setsockopt(SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)); server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) server.bind((addr, port)) server.listen(1) while True: client, addr = server.accept() message = get_message(client) print(message) response = server_response(message) send_message(client, response) client.close()
def main(): global server global client server = socket(AF_INET, SOCK_STREAM) try: addr = sys.argv[1] except IndexError: SERVER_LOGGER.warning("Нет адреса, использован стандартный") addr = '' try: port = int(sys.argv[2]) except IndexError: SERVER_LOGGER.warning("Выбран стандарный порт: 7777") port = 7777 except ValueError: SERVER_LOGGER.warning("Порт должен быть целым числом") sys.exit(0) # a.setsockopt(SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)); server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) server.bind((addr, port)) server.listen(1) while True: client, addr = server.accept() SERVER_LOGGER.debug("1. Подтверждение") message = get_message(client) SERVER_LOGGER.debug("2. Получение сообщения") print(message) SERVER_LOGGER.info('Message: ' + str(message)) response = server_response(message) SERVER_LOGGER.debug("3. Отправка ответа") send_message(client, response) client.close()
def write_responses(messages, w_clients, all_clients): for sock in w_clients: for message in messages: try: response = server_response(message) send_message(sock, response) except: print('Client {} {} disconnected'.format( sock.fileno(), sock.getpeername())) sock.close() all_clients.remove(sock)
def main(): client = socket(AF_INET, SOCK_STREAM) try: addr = sys.argv[1] except IndexError: CLIENT_LOGGER.warning("Нет адреса сервера") addr = 'localhost' try: port = int(sys.argv[2]) except IndexError: CLIENT_LOGGER.warning("Выбран стандарный порт: 7777") port = 7777 except ValueError: CLIENT_LOGGER.error("Порт должен быть целым числом") client.close() sys.exit(0) try: mode = sys.argv[3] except IndexError: mode = 'r' CLIENT_LOGGER.debug("Начало соединения") client.connect((addr, port)) message = create_message() send_message(client, message) CLIENT_LOGGER.debug("Ожидание ответа") response = get_message(client) response = translate_message(response) print(f'Установлено соединение с сервером.') CLIENT_LOGGER.info('Ответ: ' + str(response)) if response['response'] == OK: if mode == 'r': read_messages(client) elif mode == 'w': write_messages(client) else: raise Exception("Invalid mode") # Старый код # CLIENT_LOGGER.debug("1. Соединение") # client.connect((addr, port)) # message = create_message() # CLIENT_LOGGER.debug("2. Отправка сообщения") # send_message(client, message) # CLIENT_LOGGER.debug("3. Ожидание ответа") # response = get_message(client) # response = translate_message(response) # print(response) # CLIENT_LOGGER.info('Response: ' + str(response)) client.close()
def route_client_msg(message, names, clients): """ Адресная отправка сообщений. :param message: словарь сообщения :param names: список зарегистрированных клиентов :param clients: список слушающих клиентских сокетов :return: """ if message[DESTINATION] in names and names[message[DESTINATION]] in clients: send_message(names[message[DESTINATION]], message) SERVER_LOGGER.info(f'Отправлено сообщение пользователю {message[DESTINATION]} ' f'от пользователя {message[SENDER]}.') elif message[DESTINATION] in names and names[message[DESTINATION]] not in clients: raise ConnectionError else: SERVER_LOGGER.error( f'Пользователь {message[DESTINATION]} не зарегистрирован на сервере, ' f'отправка сообщения невозможна.')
def main(): client = socket(AF_INET, SOCK_STREAM) try: addr = sys.argv[1] except IndexError: addr = 'localhost' try: port = int(sys.argv[2]) except IndexError: port = 7777 except ValueError: print('Введите целое число') client.close() sys.exit(0) client.connect((addr, port)) message = create_presence() send_message(client, message) response = get_message(client) response = translate_message(response) print(response) client.close()
def parse_client_msg(message, messages_list, sock, clients_list, names): """ обработчик сообщений клиентов :param message: словарь сообщения :param messages_list: список сообщений :param sock: клиентский сокет :param clients_list: список клиентских сокетов :param names: список зарегистрированных клиентов :return: словарь ответа """ SERVER_LOGGER.debug(f'Разбор сообщения от клиента: {message}') print(f'Разбор сообщения от клиента: {message}') # возвращает сообщение о присутствии if ACTION in message and \ message[ACTION] == PRESENCE and \ TIME in message and \ USER in message: # авторизация if message[USER][ACCOUNT_NAME] not in names.keys(): names[message[USER][ACCOUNT_NAME]] = sock send_message(sock, RESPONSE_200) else: response = RESPONSE_400 response[ERROR] = 'Имя пользователя уже занято.' send_message(sock, response) clients_list.remove(sock) sock.close() return # формирует очередь сообщений elif ACTION in message and \ message[ACTION] == MESSAGE and \ SENDER in message and \ DESTINATION in message and \ MESSAGE_TEXT in message and \ TIME in message: messages_list.append(message) return # выход клиента elif ACTION in message and \ message[ACTION] == EXIT and \ ACCOUNT_NAME in message: clients_list.remove(names[message[USER][ACCOUNT_NAME]]) names[message[USER][ACCOUNT_NAME]].close() del names[message[USER][ACCOUNT_NAME]] return # возвращает сообщение об ошибке else: response = RESPONSE_400 response[ERROR] = 'Некорректный запрос.' send_message(sock, response) return
def write_messages(client): while True: message = create_message() CLIENT_LOGGER.debug("Отправка сообщения") send_message(client, message)
def main(): # Запуск программы print('Консольный месседжер. Клиентский модуль.') # Получает ip-адрес, порт сервера, режим клиента из командной строки server_addr, server_port, client_name = parse_cmd_arguments() if not client_name: client_name = input('Введите имя пользователя: ') CLIENT_LOGGER.info( f'Запущен клиент с парамертами: ' f'адрес сервера: {server_addr}, порт: {server_port}, имя пользователя: {client_name}' ) print( f'Запущен клиент с парамертами: ' f'адрес сервера: {server_addr}, порт: {server_port}, имя пользователя: {client_name}' ) # Начало работы, приветственное сообщение try: # Создается TCP-сокет клиента client_tcp = socket(AF_INET, SOCK_STREAM) # Соединяется с сервером client_tcp.connect((server_addr, server_port)) # Формирует сообщение о присутствии presence_msg = create_presence_msg(client_name) # Отправляет сообщение о присутствии серверу send_message(client_tcp, presence_msg) # Получает и разбирает сообщение от сервера server_answer = parse_server_msg(client_tcp, client_name) CLIENT_LOGGER.info( f'Установлено соединение с сервером. Ответ сервера: {server_answer}' ) print( f'Установлено соединение с сервером. Ответ сервера: {server_answer}' ) except json.JSONDecodeError: CLIENT_LOGGER.error('Не удалось декодировать полученную json-строку') print('Не удалось декодировать полученную json-строку') sys.exit(1) except ConnectionRefusedError: CLIENT_LOGGER.critical( f'Не удалось подключиться к серверу {server_addr}:{server_port}, ' f'запрос на подключение отклонён') print( f'Не удалось подключиться к серверу {server_addr}:{server_port}, ' f'запрос на подключение отклонён') # Обмен сообщениями else: # Запускает клиентский процесс приёма сообщений print('** Запуск потока \'thread_1\' для приёма сообщений **') receiver = threading.Thread(target=parse_server_msg, args=(client_tcp, client_name)) receiver.daemon = True receiver.start() # Запускает отправку сообщений и взаимодействие с клиентом print('** Запуск потока \'thread_2\' для отправки сообщений **') user_interface = threading.Thread(target=user_controls_cmd, args=(client_tcp, client_name)) user_interface.daemon = True user_interface.start() CLIENT_LOGGER.debug('** Процессы запущены **') # Watchdog основной цикл, если один из потоков завершён, # то значит потеряно соединение или пользователь ввёл exit. # Поскольку все события обрабатываются в потоках, # достаточно завершить цикл. while True: time.sleep(1) if receiver.is_alive() and user_interface.is_alive(): continue break