Пример #1
0
def server_response(message):
    if ACTION in message and \
            message[ACTION] == PRESENCE \
            and TIME in message \
            and isinstance(message[TIME], float):
        SERVER_LOGGER.debug("Ответ от сервера: ОК")
        return {RESPONSE: 200}
    SERVER_LOGGER.warning("Ответ от сервера: ОШИБКА")
    return {RESPONSE: 400, ERROR: 'Bad Request'}
Пример #2
0
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
Пример #3
0
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_LOGGER.debug("Starting connection...")
    server.bind((addr, port))
    server.listen(15)
    server.settimeout(0.2)
    clients = []
    while True:

        client, addr = server.accept()
Пример #4
0
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'отправка сообщения невозможна.')
Пример #5
0
def parse_cmd_arguments():
    """
    Парсер аргументов командной строки
    :return: ip-адрес и порт сервера
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('-p', default=DEFAULT_PORT, type=int, nargs='?')
    parser.add_argument('-a', default='', nargs='?')

    namespace = parser.parse_args(sys.argv[1:])
    addr = namespace.a
    port = namespace.p

    # Валидация номера порта
    if port < 1024 or port > 65535:
        SERVER_LOGGER.critical(f'Попытка запуска сервера с указанием неподходящего порта '
                               f'{port}. Допустимы адреса с 1024 до 65535.')
        sys.exit(1)

    return addr, port
Пример #6
0
def main():
    # извлекает ip-адрес и порт из командной строки
    listen_addr, listen_port = parse_cmd_arguments()

    # создает TCP-сокет сервера
    server_tcp = socket(AF_INET, SOCK_STREAM)

    # связывает сокет с ip-адресом и портом сервера
    server_tcp.bind((listen_addr, listen_port))

    # таймаут для операций с сокетом
    server_tcp.settimeout(0.5)

    # запускает режим прослушивания
    server_tcp.listen(MAX_CONNECTIONS)

    SERVER_LOGGER.info(
        f'Запущен сервер, порт для подключений: {listen_port}, '
        f'адрес с которого принимаются подключения: {listen_addr}. '
        f'Если адрес не указан, принимаются соединения с любых адресов.')

    print(f'Запущен сервер, порт для подключений: {listen_port}, '
          f'адрес с которого принимаются подключения: {listen_addr}.')

    # список клиентов и очередь сообщений
    all_clients = []
    all_messages = []

    # словарь зарегистрированных клиентов: ключ - имя пользователя, значение - сокет
    all_names = dict()

    while True:
        # принимает запрос на соединение
        # возвращает кортеж (новый TCP-сокет клиента, адрес клиента)
        try:
            client_tcp, client_addr = server_tcp.accept()
        except OSError:
            pass
        else:
            SERVER_LOGGER.info(
                f'Установлено соедение с клиентом {client_addr}')
            print(f'Установлено соедение с клиентом {client_addr}')
            all_clients.append(client_tcp)

        r_clients = []
        w_clients = []
        errs = []

        # запрашивает информацию о готовности к вводу, выводу и о наличии
        # исключений для группы дескрипторов сокетов
        try:
            if all_clients:
                r_clients, w_clients, errs = select.select(
                    all_clients, all_clients, [], 0)
        except OSError:
            pass

        # чтение запросов из списка клиентов
        if r_clients:
            for r_sock in r_clients:
                try:
                    parse_client_msg(receive_message(r_sock), all_messages,
                                     r_sock, all_clients, all_names)
                except Exception as ex:
                    SERVER_LOGGER.error(
                        f'Клиент отключился от сервера. '
                        f'Тип исключения: {type(ex).__name__}, аргументы: {ex.args}'
                    )
                    all_clients.remove(r_sock)

        # роутинг сообщений адресатам
        for msg in all_messages:
            try:
                route_client_msg(msg, all_names, w_clients)
            except Exception:
                SERVER_LOGGER.info(
                    f'Связь с клиентом {msg[DESTINATION]} была потеряна')
                all_clients.remove(all_names[msg[DESTINATION]])
                del all_names[msg[DESTINATION]]
        all_messages.clear()
Пример #7
0
            messages.append(message)
        except BaseException:
            print('Client {} {} disconnected'.format(sock.fileno(),
                                                     sock.getpeername()))
            all_clients.remove(sock)

    return messages


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)


# Спасибо stackoverflow за эту подсказку
if __name__ == '__main__':
    SERVER_LOGGER.info("Сервер запущен")
    try:
        main()
    except Exception as e:
        SERVER_LOGGER.error("Exception: {}".format(str(e)))
    SERVER_LOGGER.info("Сервер остановлен")
Пример #8
0
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()