Компьютерные сети 2018, задачи
1. getaddrinfo(), inet_ntop(), ntohs()
1.1 Порядок байт, strtol()
Написать программу, которая получает один обязательный аргумент командной строки - беззнаковое целое 32-битное число, записывает его в переменную, и затем выводит содержимое ячеек памяти, в которых хранится эта переменная (в порядке возрастания адресов).
1.2 Порядок байт, strtol(), htonl()
Добавить к предыдущей программе преобразование полученного числа в сетевой порядок байт. Вывести результат (также в порядке возрастания адресов). Сравнить с выводом предыдущей программы.
1.3 Порядок байт, strtol(), htonl(), inet_ntop()
Добавить к предыдущей программе преобразование полученного числа с сетевым порядком байт в презентационный формат (строка) для AF_INET (IPv4) и вывод получившейся строки
>./a.out 0x01020304 host byte order: s_addr=0x01020304, 0x04:0x03:0x02:0x01 network byte order: s_addr=0x04030201, 0x01:0x02:0x03:0x04 s=1.2.3.4
1.4 getaddrinfo(), IPv4
Написать программу, которая получает один обязательный аргумент командной строки - доменное имя, и выдает все IPv4-адреса для этого имени.
1.5 getaddrinfo(), IPv4, IPv6
Модифицировать программу из п. 1.4 так, чтобы она выдавала еще и IPv6-адреса.
1.6 getaddrinfo(), IPv4, IPv6, номер порта
Модифицировать программу из п. 1.5 так, чтобы она получала два обязательных аргумента командной строки - доменное имя и имя сервиса и выдавала вместе с IPv4 или IPv6 адресами номер порта для подключения
Можно использовать task1.c как образец для задач 1.4-1.6
2. getnameinfo(), inet_pton()
2.1 inet_pton()
Написать программу, которая получает один обязательный аргумент командной строки - IPv4 адрес в строковом формате (aaa.bbb.ccc.ddd) и с помощью функции inet_pton() преобразует адрес во внутреннее представление. Вывести результат (можно использовать код из п.1.2)
2.2 inet_pton(), getnameinfo()
Добавить к программе из п.2.1 получение доменного имени для получившегося адреса с помощью функции getnameinfo(), вывести доменное имя (если есть).
2.3 inet_pton(), getnameinfo()
Модифицировать программу из п.2.3 так, чтобы она получала два обязательных аргумента командной строки - IPv4 адрес в строковом формате и номер порта, с помощью функции getnameinfo() получить доменное имя и имя сервиса, вывести (если есть).
3. Установка исходящего TCP-соединения
3.1 struct addrinfo *hints
Добавить к программе из п.1.6 ограничение на поиск адресов: искать только IPv4 и TCP
3.2 ai_family, ai_socktype, ai_protocol, socket()
Добавить к предыдущей программе создание сокета для первого найденного функцией getaddrinfo() значения
3.3 socket(), connect()
Добавить к предыдущей программе установку исходящего TCP-соединения на адрес из первого найденного функцией getaddrinfo() значения
3.4 socket(), connect(), write() или send()
Добавить к предыдущей программе отправку простейшего HTTP/1.0 запроса (GET /)
3.5 socket(), connect(), read() или recv()
Добавить к предыдущей программе копирование ответа удаленной стороны на стандартный вывод
> netcat -vv ya.ru 80 Connection to ya.ru 80 port [tcp/http] succeeded! GET / HTTP/1.0 Host: ya.ru HTTP/1.1 302 Found Date: Tue, 20 Feb 2018 07:17:25 GMT Cache-Control: no-cache,no-store,max-age=0,must-revalidate Location: https://ya.ru/ Expires: Tue, 20 Feb 2018 07:17:26 GMT Last-Modified: Tue, 20 Feb 2018 07:17:26 GMT P3P: policyref="/w3c/p3p.xml", CP="NON DSP ADM DEV PSD IVDo OUR IND STP PHY PRE NAV UNI" Set-Cookie: yandexuid=9922938791519111045; Expires=Fri, 18-Feb-2028 07:17:25 GMT; Domain=.ya.ru; Path=/ X-Content-Type-Options: nosniff Content-Length: 0
3.6 socket(), connect(), getsockname()
Добавить к предыдущей программе получение адреса, автоматически назначенного локальному сокету, с помощью функции getsockname(), и вывод его в строковом формате
4. Передача данных по UDP
4.1 struct addrinfo *hints
Модифицировать программу из п.3.1: искать только IPv4 и UDP
4.2 ai_family, ai_socktype, ai_protocol, socket()
Добавить к предыдущей программе создание сокета для первого найденного функцией getaddrinfo() значения
4.3 socket(), sendto(), recvfrom()
Добавить к предыдущей программе отправку произвольной строки на первый адрес, найденный getaddrinfo(), и получение ответа. Для тестирования используйте echo-сервер на kappa.cs.prv
> echo qwerty | netcat -q -u kappa.cs.petrsu.ru echo qwerty
4.4 socket(), connect(), send(), recv()
Модифицировать программу из п.4.2: сохранить первый адрес, найденный функцией getaddrinfo(), с помощью connect(), затем отправлять данные с помощью функции send().
5. UDP: socket(), recvfrom()
5.1. strtol() или getaddrinfo(), socket(), bind(), recvfrom()
Написать программу, которая получает один обязательный аргумент командной строки - номер порта. Далее нужно создать UDP-сокет, назначить ему полученный номер порта с помощью функции bind(), принимать данные через созданный сокет и копировать их на стандартный вывод программы
5.2. getnameinfo()
Добавьте к предыдущей программе вывод адреса удаленного сокета, с которого пришло сообщение
5.3. getnameinfo(), sendto()
Модифицируйте программу из п.5.2 так, чтобы полученные данные отправлялись обратно отправителю (в результате должен получиться свой UDP echo-сервер).
5.4 connect()
Модифицируйте программу из п.5.1: добавьте два обязательных параметра командной строки: имя и номер порта, с которых принимать сообщения. После создания сокета установите для него указанный адрес удаленного сокета с помощью функции connect(). Покажите, что после этого сообщения с других адресов не принимаются.
Для тестирования можно использовать утилиту netcat или программу из п.4 (указав свой номер порта)
> netcat -u -s 127.0.0.1 -p 3333 127.0.0.1 2222 qwerty qwerty
6. TCP: прием одного входящего соединения.
6.1. strtol() или getaddrinfo(), socket(), bind(), listen(), accept().
Написать программу, которая получает один обязательный аргумент командной строки - номер порта. Далее нужно создать TCP-сокет, назначить ему полученный номер порта с помощью функции bind(), включить прием входящих соединений с помощью функции listen() и принять одно входящее соединение с помощью accept().
6.2. getpeername(), getnameinfo()
Добавьте к предыдущей программе вывод адреса удаленного сокета, с которого пришло сообщение
6.3. send() или write()
Модифицируйте программу из п.6.2 так, чтобы полученные данные отправлялись обратно отправителю (в результате должен получиться свой TCP echo-сервер).
Для тестирования можно использовать утилиты netcat или telnet
7. Прием и обработка нескольких входящих TCP-соединений
7.1 TCP с fork()
Модифицируйте программу из п.6.3 таким образом, чтобы для каждого установленного соединения порождался новый процесс с echo-сервером. После закрытия соединения порожденный процесс должен корректно завершаться (не оставаться в состоянии zombie).
7.2 TCP с select()
Модифицируйте программу из п.6.3 таким образом, чтобы все установленные соединения обрабатывались с помощью мультиплексирования ввода-вывода (функция select() или аналоги). Для передачи ответа тоже должно использоваться мультиплексирование ввода-вывода (функция select() или аналоги).