Это репозиторий, содержащий код для студентов, проходящих курс "Сетевое программирование на C++" в GeekBrains.
- Начало работы
- FAQ
- Как сделать домашнее задание, чтобы преподаватель его посмотрел?
- Я художник, я так вижу, мне плевать на правила оформления.
- Надо ли обновляться и как?
- Где все примеры?
- Как собрать примеры?
- Сборка не проходит, вообще не собирается ничего.
- Почему используется Linux?
- Могу ли я собрать код на Windows?
- А есть что-то про CMake?
- Docker - что это?
- Как запустить собранное?
- Как запустить консоль?
- Где взять Netcat под Windows?
- Всё делаю правильно, но что-то не подключается.
- Я нашёл ошибку в коде, могу ли я её исправить?
- А у меня вопрос!
Чтобы начать работать:
- Если Docker не установлен в системе, установите его.
- Если Git не установлен в системе, установите его.
- Склонируйте репозиторий:
git clone https://github.com/artiomn/cpp-network-tasks.git
.
Внимание: склонируйте репозиторий в каталог, содержащий только латинские символы в пути! - Зайдите в каталог
cpp-network-tasks
. - Запустите скрипт
./build_dockerized.sh
Если это первый запуск, пройдёт значительное время перед тем, как вы получите результат.
Возможно, что вам потребуется установить Docker.
Для запуска IDE QtCreator выполните из каталога cpp-network-tasks
следующую команду: ./run -q
.
Будет запущена IDE, в которой необходимо открыть, как проект, файл CMakeLists.txt
в каталоге /home/developer/src
или /usr/src/gb/src
(первый каталог - ссылка).
Чтобы ваше задание не получило статус "Не сдано" автоматически, ещё до проверки его преподавателем, выполните несколько правил:
- Проверьте, что код скомпилируется.
- Для сборки используйте CMake.
- Оформите код согласно кодовому стилю.
Подходящий вариант стиля для ClangFormat находится в репозитории: code-style.clang-format.
* Файл стиля был предоставлен Henryk ll Selenya.
Пример оформления вы увидите в примерах к уроку.
Кратко:
- В качестве отступов используются пробелы.
- Ширина отступа 4 пробела.
- Открывающая фигурная скобка на следующей строки после имени.
- После
if
,for
и подобных операторов - один пробел до скобки. - После имён функций и методов нет пробелов.
- После открывающей и перед закрывающей круглыми скобками нет пробелов.
- После каждой запятой и точки с запятой - пробел.
- Названия классов пишутся в
CamelCase
. - Названия функций, методов и переменных - в
snake_case
. - Между реализациями функция и методов ставится две пустые строки.
- Внутри тела функций и методов не допускается более одной пустой строки.
- Атрибуты классов оканчиваются на
_
. - Комментарии желательно оставлять на английском языке. В примерах они, местами, на русском. Исключительно потому, что примеры учебные.
Правильный вариант оформления:
int main()
{
std::cout
<< "Getting name for \"" << host_name << "\"...\n"
<< "Using getaddrinfo() function." << std::endl;
addrinfo hints =
{
.ai_flags= AI_CANONNAME,
// Неважно, IPv4 или IPv6.
.ai_family = AF_UNSPEC,
// TCP stream-sockets.
.ai_socktype = SOCK_STREAM,
// Any protocol.
.ai_protocol = 0
};
// Results.
addrinfo *servinfo = nullptr;
int status = 0;
if ((status = getaddrinfo(host_name.c_str(), nullptr, &hints, &servinfo)) != 0)
{
std::cerr << "getaddrinfo error: " << gai_strerror(status) << std::endl;
return EXIT_FAILURE;
}
for (auto const *s = servinfo; s != nullptr; s = s->ai_next)
{
std::cout << "Canonical name: ";
if (s->ai_canonname)
std::cout << s->ai_canonname;
std::cout << "\n";
assert(s->ai_family == s->ai_addr->sa_family);
std::cout << "Address type: ";
if (AF_INET == s->ai_family)
{
char ip[INET_ADDRSTRLEN];
std::cout << "AF_INET\n";
sockaddr_in const * const sin = reinterpret_cast<const sockaddr_in* const>(s->ai_addr);
std::cout << "Address length: " << sizeof(sin->sin_addr) << "\n";
in_addr addr = { .s_addr = *reinterpret_cast<const in_addr_t*>(&sin->sin_addr) };
std::cout << "IP Address: " << inet_ntop(AF_INET, &addr, ip, INET_ADDRSTRLEN) << "\n";
}
else if (AF_INET6 == s->ai_family)
{
char ip6[INET6_ADDRSTRLEN];
std::cout << "AF_INET6\n";
}
else
{
std::cout << s->ai_family << "\n";
}
std::cout << std::endl;
}
std::cout << std::endl;
freeaddrinfo(servinfo);
return EXIT_SUCCESS;
}
Ваша работа сразу автоматически отправляется в помойку.
Иногда - надо. Когда в код или образ вносятся изменения, о чём вам должны сообщить. Если вы работаете с Git репозиторием, код обновляется следующим образом:
git pull
Если вам предоставляется архив, преподаватель обновит его сам.
Docker образы могут быть обновлены следующими командами:
artiomn/gb-build-image
artiomn/gb-qt-creator-image
Те, что сделаны, - в надёжном месте. Они будут добавляться по мере прохождения уроков.
Доступные вам примеры находятся в каталоге src/l<номер_урока>
.
Сборка производится, используя CMake, поэтому:
- Вы можете использовать любую современную IDE для сборки.
- Скрипт
./build.sh
. - Прямой запуск CMake.
Проблемой является то, что сборка не подгружает зависимости.
Поэтому, для того, чтобы собрать без необходимости заниматься установкой множества пакетов, используется подготовленная среда.
Она представляет собой Docker-контейнер, образ которого лежит на docker.hub.
Сборка в ней запускается через скрипт ./build_dockerized.sh
.
Под Windows сборка была проверена на MSVS 2019 и собранные артефакты будут находиться в src\out\build\windows-default\bin
.
Собираться под Windows будет не всё, есть примеры только под Linux.
Может быть несколько причин из-за которых не проходит сборка. Для начала, убедитесь, что у вас:
- Правильно настроен и работает Docker.
- Если это первая сборка, есть доступ в Интернет.
Далее, проверьте, что каталог в котором производится сборка, не содержит в пути не латинских символов, пробелов и спецсимволов.
Не делайте каталог вида: ~/Общедоступные/user/geekbrains/lessons/C++-network/Programming_Lessons & Code/Репозиторий!/cpp-network-tasks
.
Для большинства сборок - это верный путь к проблемам, о которых не знали разработчики.
Положите репозиторий в каталог с нормальным именем, например ~/projects/cpp-network-tasks
.
Если вы уже собирали проект локально и хотите собрать его в Docker или, наоборот, собирали в Docker и хотите собрать локально, CMake выдаст ошибку, похожую на следующую:
CMake Error: The current CMakeCache.txt directory /home/user/projects/cpp-network-tasks/build/CMakeCache.txt is different than the directory /usr/src/gb/build where CMakeCache.txt was created. This may result in binaries being created in the wrong place. If you are not sure, reedit the CMakeCache.txt
CMake Error: The source "/home/artiom/user/cpp-network-tasks/src/CMakeLists.txt" does not match the source "/usr/src/gb/src/CMakeLists.txt" used to generate cache. Re-run cmake with a different source directory.
Что говорит о том, что конфигурации CMake различаются, вы запускаете его в разном окружении.
Чтобы исправить это, удалите каталог build
и запустите сборку заново:
➭ rm -rf build && ./build_dockerized.sh
- Потому что, на Linux и BSD системах работают большинство сетевых приложений.
- На Linux работает автор курсов.
- Кроме Linux есть множество других ОС, и рассмотреть особенности каждой невозможно.
- Перевод кода на Windows оговорён.
- По возможности, код и так кроссплатформенный.
Да, возможно собрать часть кода. Сборка проверялась на MS Visual Studio 2019.
Чтобы собрать код, надо открыть корневой CMakeLists.txt, как CMake проект.
Но есть следующие проблемы:
- Есть код специфичный для Linux, например перехватчик вызовов, который будет собираться и работать только на этой платформе.
- Некоторый код просто не был адаптирован для Windows, и его сборка выключена.
- Есть редкие примеры, которые собираются, но работать корректно не будут (один из таких - асинхронный сервер на
select()
). Оно не работает, потому что не было достаточно времени и мотивации, чтобы доработать под Windows. Если вы считаете, что можете доделать такой код - You're welcome. - В Windows есть не все библиотеки, а CMake не имеет, например модуля для поиска Qt, если Qt не установлен. Это приводит к тому, что пример не просто нельзя собрать, если чего-то не хватает, а падает сборка. Конечно, возможно это исправить, если вы считаете, что нужно, репозиторий открыт для правок.
Также, есть некоторый код, специфичный для Windows, но в уроках он, как правило, не упоминается.
Есть:
- Вебинар GB, который вы должны были смотреть к началу курса.
- Документация.
- Статьи.
- Много информации в Интернете.
Предполагается, что в процессе работы с курсом, вы будете активно использовать поиск.
Соответственно, Google поможет.
Если очень кратко, Docker - это один из вариантов реализации автоматизации инфраструктуры контейнеризации.
Он позволяет изолировать приложения в контейнерах, образы которых скачаны из репозитория.
Здесь он нужен для того, чтобы:
- Вы могли собрать код, не устанавливая лишних библиотек.
- Вы могли проверить сборку тем же самым компилятором, что и проверяющий.
Напомню, что образ с инструкциями лежит на Docker.hub. У GeekBrains есть поясняющее видео про C++ в Docker.
На Windows только вместе с Linux подсистемой.
На Linux его надо установить, а как, зависит от вашего дистрибутива.
Например, в deb-based это делается по следующей инструкции.
Управлять Docker, в том числе и запускать или останавливать контейнеры могут только:
- Пользователь
root
. - Пользователи в группе
docker
.
Добавить вашего пользователя в группу Docker возможно по-разному. Один из вариантов, который будет работать для многих дистрибутивов:
$ sudo usermod -a -G docker "${USER}"
После этого надо завершить сессию, например выйти на Login Screen, и снова войти.
Это зависит от IDE. Возможно использовать удалённую сборку по SSH (сервер установлен в образе), некоторые IDE, такие как CLion, поддерживают работу с Docker напрямую.
Пример настройки CLion показан здесь.
Настройки конфигурации Docker показаны на скриншоте:
Настройки конфигурации CMake:
Раньше QtCreator не поддерживал удалённую сборку по SSH.
Есть вариант настройки с подмонтированием каталога через SSHFS. Но все пути к инклудам, а также библиотекам, естественно, будут некорректны, т.к. в контейнере они другие.
Возможно самый просто вариант - установить QtCreator в контейнер и запустить оттуда. На данный момент для этого собран образ. Чтобы запустить его, используйте:
./run -q
Проверьте:
- Установлен ли у вас Docker. Если нет - установите.
- Достаточно ли прав у вашего пользователя, что с Docker взаимодействовать.
В большинстве дистрибутивов, при установке Docker создаёт группу docker
, что вы можете проверить, выполнив следующую команду:
$ grep docker /etc/group
docker:x:997:
Видно, что пользователя в этой группе нет. Добавьте его туда:
$ sudo usermod -a -G docker "$USER"
$ grep docker /etc/group
docker:x:997:artiom
После того, как вы перелогинитесь в системе, группа будет видна:
$ groups
sys network power video storage lp input audio wheel artiom docker
Возможно, образ устарел. Обновите его:
$ docker pull artiomn/gb-build-image
Using default tag: latest
latest: Pulling from artiomn/gb-build-image
Digest: sha256:be8e76c39543bd03f503a294d96dc578c5ad90b77c1473e6b03ef1feb88c0b0c
Status: Downloaded newer image for artiomn/gb-build-image:latest
docker.io/artiomn/gb-build-image:latest
Можете. Контейнер запускается в privileged режиме. Т.е. из него возможно создавать устройства, а значит испортить всё, что угодно. Это требуется для того, чтобы сети, в частности Yggdrasil, могли создать TUN устройство.
Если вы производили сборку, как указано выше, собранные бинарные файлы будут находиться в каталоге build/bin
.
Запустить вы их можете напрямую, однако из-за отсутствующих в системе зависимостей работать может не всё.
Поэтому, запуск также производится в контейнере, используя команду ./run
, которой передаются необходимые приложению аргументы и путь к нему.
Пример:
➭ ./run sudo ./build/bin/ping google.com
Pinging "google.com" [64.233.165.113]
Start to sending packets...
Sending packet 0 to "google.com" request with id = 29
Receiving packet 0 from "google.com" response with id = 29, time = 15.5ms
./run
docker-compose run --rm gb
- для тех, кто пользуется docker-compose.
Обратите внимание: консоль запускается через скрипт ./run
в корне репозитория, не через docker run
.
Например, здесь.
Внимание!
Windows Defender может заблокировать Netcat, определив его, как Netcat.Hacktool.
В таком случае, просто отключите "защиту реального времени".
Такая проблема была у одного из студентов. Он выяснил, что Netcat подключался на IPv6 адрес, тогда как сервер прослушивал только IPv4.
Как исправить? Зависит от приложения. Задайте ему не доменное имя, а IPv4 адрес явно, при возможности.
Для Netcat возможно использовать опцию -4
(не все реализации её поддерживают).
Да. Следуя обычному процессу Guthub:
- Сначала делаете форк репозитория.
- Клонируете его, исправляете ошибку.
- Делаете Pull request.
Или просто можете просто завести Issue. Но, в этом случае, обещать быстрое исправление я не могу.
Замечательно. Но прежде, чем задавать его преподавателю, вы пробовали найти ответ? Возможно, что его надо лишь поискать? У преподавателя не так много времени для того, чтобы делать это за вас. Если ответа нет - задавайте.