Лабораторная №2 Создание простейшего приложения с использованием сокетов Беркли. Цель: Получение опыта создания приложений, использующих сетевые интерфейсы транспортного уровня. План: 1. Рассчитать персональный вариант и определить используемый в работе протокол транспортного уровня, а также выполняемую роль в передаче данных (сервер или клиент); 2. Изучить методы работы с сетевыми интерфейсами при помощи API сокетов Беркли; 3. Написать программу, выполняющую обмен данными по сетевому интерфейсу в соответствии с персональным вариантом и выполнить ее компиляцию в Linux; 4. Протестировать работу программы Ход: 1. Персональный вариант для лабораторной работы определяется следующим образом: если (|Ф| % 2 == 1), то протокол UDP, иначе TCP если (|И| % 2 == 1), то клиент, иначе сервер. Остальные исходные данные для лабораторной работы: порт TCP = 43521 порт UDP = 43522 клиент отсылает "Фамилию Имя Отчество\n" студента на IP адрес сервера 127.0.0.1, на порт, соответствующий протоколу. сервер принимает соединение с любого IP адреса (INADDR_ANY) и порта, соответствующий протоколу. 2. Методы работы с сетевыми интерфейсами при помощи API Сокетов Беркли Основные используемые функции: int socket(int domain, int type, int protocol); - создание сокета domain ("домен" коммуникации) = PF_INET (для IPv4 в стеке TCP/IP) type (тип коммуникации) = SOCK_STREAM (для TCP) || SOCK_DGRAM (для UDP) protocol (задает конкретный протокол) IPPROTO_TCP || IPPROTO_UDP uint16_t htons(uint16_t hostshort); преобразование в сетевой порядок байт 16-битного слова (используется для задания порта) int inet_pton(int af, const char *src, void *dst); Преобразование символьных IPv4 и IPv6 адресов в бинарный формат af - тип сетевого адреса (AF_INET | AF_INET6) src - строка dst(out) - бинарный формат return 1 - успех, 0 - неверный адрес, -1 - неверный тип сетевого адреса int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); Установка соединения с протоколами с соединением sockfd - дескриптор serv_addr - сокет для соединения addrlen - длина адреса в байтах return: 0 - успех, -1 - ошибка int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen); Связывание с сокетом для дальнейшего прослушивание; sockfd - дескриптор my_addr - локальный адрес addrlen - длина адреса return: 0 - успех, -1 - ошибка int listen(int s, int backlog); слушать соединения на сокете s - дескриптор backlog - длина очереди соединений return: 0 - успех, -1 - ошибка int accept(int s, struct sockaddr *addr, socklen_t *addrlen); принять соединение на сокете s - дескриптор addr - помещается адрес другой стороны, которая совершает соединения addrlen - помещается размер адреса return: дескриптор нового сокета, -1 - ошибка int shutdown(int s, int how); перекрыть часть дуплексного соединения (для интерфейсов с соединением) s - дескриптор how - 0-прием 1-передача 2-прием и передача return: 0 - успех, -1 - ошибка int close(int fd); Универсальная функция закрытия дескриптора fd - дескриптор return: 0 - успех, -1 - ошибка консольные команды: man 2 send - справка по функциям посылки информации через сокет man 2 recv - справка по функциям принятия информации через сокет Создание сервера/клиента TCP/UDP предполагает определенный алгоритм работы. Алгоритм работы TCP-сервера: 1. Создание сокета, принимающего входные соединения, при помощи функции socket() 2. Сознание и заполнение адреса прослушиваемого сокета при помощи структуры struct sockaddr_in sockaddr_in.sin_port- порт в big-edndian sockaddr_in.sin_addr.s_addr - IP-адрес в бинарном формате (для сервера, слушающего все интерфейсы используется константа INADDR_ANY) 3. Связывание адреса сокета и созданного сокета при помощи функции bind() 4. Установка сокета на прослушивание при помощи функции listen() 5. Прием входного подключения и получение нового сокета входного подключения при помощи функции accept() 6. Выполнение операций чтения/записи при помощи семейства функций recv/send соответственно 7. Разрыв входного TCP соединения (входного сокета) при помощи функции shutdown() 8. Закрытие входного сокета при помощи функции close() 9. Закрытие принимающего сокета при помощи функции close() Алгоритм работы TCP-клиента: 1. Создание сокета соединения при помощи функции socket() 2. Сознание и заполнение адреса серверного сокета, к которому устанавливается соединение при помощи структуры struct sockaddr_in sockaddr_in.sin_port- порт в big-edndian sockaddr_in.sin_addr.s_addr - IP-адрес в бинарном формате (для сервера, слушающего все интерфейсы используется константа INADDR_ANY) 3. Установка соединения с сервером через сокет при помощи функции connect() 4. Выполнение операций чтения/записи при помощи семейтва функций recv/send соответственно 5. Разрыв TCP соединения при помощи функции shutdown() 6. Закрытие сокета при помощи функции close() Алгоритм работы UDP-сервера: 1. Создание сокета, принимающего датаграммы, при помощи функции socket() 2. Сознание и заполнение адреса прослушиваемого сокета при помощи структуры struct sockaddr_in sockaddr_in.sin_port- порт в big-edndian sockaddr_in.sin_addr.s_addr - IP-адрес в бинарном формате (для сервера, слушающего все интерфейсы используется константа INADDR_ANY) 3. Связывание адреса сокета и созданного сокета при помощи функции bind() 4. Выполнение операций чтения/записи при помощи семейтва функций recv/send соответственно 5. Закрытие сокета при помощи функции close() Алгоритм работы UDP-клиента: 1. Создание сокета, принимающего датаграммы, при помощи функции socket() 2. Сознание и заполнение адреса отсылаемой датаграммы при помощи структуры struct sockaddr_in sockaddr_in.sin_port- порт в big-edndian sockaddr_in.sin_addr.s_addr - IP-адрес в бинарном формате (для сервера, слушающего все интерфейсы используется константа INADDR_ANY) 3. Выполнение операций чтения/записи при помощи семейства функций recv/send соответственно 4. Закрытие сокета при помощи функции close() 3. Написать программу, выполняющую обмен данными по сетевому интерфейсу в соответствии с персональным вариантом и выполнить ее компиляцию в Linux; Для написания программы возможно использование следующих инструментов на выбор: netbeans-cpp - многофункциональная интегрированная среда разработки, со встроенными средствами сборки codeblocks - интегрированная среда разработки на языках C/C++, со встроенными средствами сборки geany - удобный редактор с подсветкой синтаксиса; nano - консольный удобный редактор с подсветкой синтаксиса; gcc - компилятор С 4. Протестировать работу программы Для вариантов с реализацией сервера тестирование осуществлять по следующему алгоритму: 1. Запустить написанную программу-сервер; 2. В другом терминале выполнить подключение к серверу при помощи утилиты socat: Для TCP: socat tcp:127.0.0.1:43521 stdio Для UDP: socat udp:127.0.0.1:43522 stdio 3. В терминале socat набрать сообщение и отправить при помощи клавиши Enter; 4. Убедиться в приеме сообщения программой-сервером. Для вариантов с реализацией клиента тестирование осуществлять по следующему алгоритму: 1. В терминале запустить сервер при помощи утилиты socat: Для TCP: socat tcp-listen:43521 stdio Для UDP: socat udp-listen:43522 stdio 2. В другом терминале запустить программу-клиент отправляющую ФИО студента; 3. Убедиться в наличии сообщения в терминале socat.