Лабораторная работа № 8. Использование механизма сокетов с сетевыми протоколами, не ориентированными на установление соединения

Цель: Изучение механизма сокетов в операционной системе Windows.

Задачи:

1. Изучение теоретического материала по сокетам с сетевыми протоколами, не ориентированными на установление соединения.

2. Составление алгоритма программы.

3. Программная реализация.

Ход работы:

1. Ознакомиться с описанием функций WinSock API, которые служат для работы с протоколами, которые не устанавливают соединение.

2. Модифицировать обе программы, написанные в ходе выполнения лабораторной работы №8, используя сетевые протоколы без установления логического соединения (UDP).

3. Написать отчет и представить его к защите вместе с исполняемыми модулями программ и их исходными текстами. Программы должны позволять взаимодействовать, будучи запущенными на разных рабочих станциях.

Ход защиты:

1. Продемонстрировать преподавателю программы, использующие сетевые протоколы без установления логического соединения.

2. Пояснить программный код разработанных приложений.

Основная цель разработки спецификации WinSock 2 – создание независимого от протоколов транспортного интерфейса.

Перед использованием сокетов необходимо загрузить корректную версию библиотеки WinSock с помощью функции инициализации

int WSAStartup (

WORD Version, // номер версии

LPWSADATA Data); // информация о версии

На современных платформах Win 32 используется версия 2.2. Чтобы
загрузить библиотеку этой версии нужно вызвать WSAStartUp следующим образом.

#include <winsock2.h>

#include <stdio.h>

#include <stdlib.h>

# pragma comment (lib, “ws2_32.lib”)

void main(void)

{

WSADATA wsData;

if (WSAStartup (0x0202, &wsData)!= 0) {

printf ("Невозможно загрузить Winsock 2.2\n");

exit (1);

}

printf("Библиотека инициализирована.\n");

WSACleanup ();

}

Для завершения работы с WinSock необходимо вызвать WSACleanup, которая освобождает занятые ресурсов.

void WSACleanup (void);

Связь без установления соединения выполняется при помощи пользовательских дейтаграмм протокола UDP. Он не гарантирует надежности,
однако может осуществлять передачу данных нескольким адресатам и принимать их от нескольких источников. В частности, данные, отправляемые клиентом, передаются на сервер немедленно, независимо от готовности (или неготовности) сервера. При получении данных сервер не подтверждает их прием. Данные передаются порциями, называемыми дейтаграммами.

При использовании протокола IP устройствам назначается 32-разрядный IP -адрес версии 4. Для взаимодействия с сервером по TCP клиент должен указать IP -адрес сервера и номер порта службы. Чтобы прослушивать входящие запросы клиента, сервер тоже должен указать IP -адрес и номер порта. В Winsock IP -адрес и порт службы указываются в структуре SOCKADDR_IN:

struct sockaddr_in {

short sin_family; // для IP должен использоваться AF_INET

u_short sin_port;

// любой свободный порт из диапазона (1024, 65535)

struct in_addr sin_addr; // IP-адрес в 4-байтном виде

char sin_zero[8]; // заполнитель нулями

};

Вспомогательная функция inet_addr преобразует IP -адрес из точечной нотации в беззнаковое длинное целое число, в котором байты следуют в соответствии с сетевым порядком следования:

unsigned long inet_addr (const char FAR * cp);

// строка с адресом в десятично-точечной нотации

Существуют два специальных адреса INADDR_ANY, который позволяет серверу слушать клиента через любой сетевой интерфейс на несущем компьютере, и INADDR_BROADCAST, позволяющие широковещательно рассылать дейтаграммы по сети.

Несколько замечаний относительно порядка следования байтов. В процессорах x 86 и Pentium представляют многобайтные числа от менее значимого байта к более значимому. В частности, IP -адрес и номер порта хранятся в памяти именно так. Это так называемый системный порядок. При передаче их по сети стандарты требуют, чтобы многобайтные значения представлялись от старшего байта к младшему, что называется сетевым порядком.
Две следующие функции позволяют преобразовывать, соответственно, 4- и 2-байтовые числа из системного порядка в сетевой.

u_long htonl(u_long hostlong);

u_short htons (u_short hostshort);

Следующие две функции решают обратную задачу, т. е. переставляют байты из сетевого порядка в системный:

u_long ntohl(u_long netlong);

u_short ntohs (u_short netshort);

Следующий фрагмент демонстрирует, как создается структура с адресом и номером порта при помощи описанных функций.

SOCKADDR_IN InetAddr;

INT PortNum = 5101;

InetAddr.sin_family = AF_INET;

InetAddr.sin_addr.s_addr = inet_addr ("192.168.123.45");

InetAddr.sin_port.htons (PortNum);

Процесс получения данных на сокете, не требующем соединения, прост. Сокет создается функцией

SOCKET socket (

int af, // семейство адресов протокола

// (для IP надо указать AF_INET)

int type, // тип сокета (для UDP надо указать SOCK_DGRAM)

int namelen); // транспорт (для UDP - IPPROTO_UDP)

Открыть IP -сокет при помощи протокола UDP можно следующим
образом.

sock_udp = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);

Затем осуществляется привязка сокета к интерфейсу, на котором будут приниматься данные, с помощью функции bind (аналогично протоколам, ориентированным на соединения). После этого нужно просто ожидать
приема входящих данных. Соединения нет, а значит, сокет-приемник получает дейтаграммы от любой станции в сети. Итак, после создания сокета конкретного протокола его надо связать со стандартным адресом при помощи
функции

int bind (

SOCKET s, // сокет, на котором ожидается прием данных

const struct sockaddr FAR* name, // универсальный буфер

int namelen); // размер буфера

При возникновении ошибки функция bind возвращает SOCKET_ERROR.

if (bind (sock1, (struct sockaddr *) addr, sizeof (addr)) ==

SOCKET_ERROR) {

printf (“bind () с ошибкой\n”);

}

В сетевом программировании главное - отправлять и принимать данные. Для пересылки используют функцию sendto, а для приема - recvfrom. Первая из них определена так:

int sendto (

SOCKET s, // сокет для отправки данных

const char FAR* buf, // буфер для отправляемых данных

int len, // число отправляемых байтов или размер буфера

int flags, // флаги

struct sockaddr FAR* to, // адрес станции-приемника

int tolen); // длина адреса применика

При успешном выполнении sendto вернет количество переданных байтов, иначе – ошибку SOCKET_ERROR. Возвращаемое количество байтов может отличаться от значения параметра len.

Функция приема аналогична отправке, она возвращает количество полученных байтов. Если сокет к этому времени был уже закрыт, то возвращаемым значением является 0. Если же возникла ошибка – SOCKET_ERROR.

int recvfrom (

SOCKET s, // сокет для приема данных

char FAR* buf, // буфер с данными для получаемых данных

int len, // число принимаемых байтов или размер буфера

int flags, // флаги

struct sockaddr FAR* from, // адрес станции-отправителя

int FAR* fromlen); // длина адреса отправителя

По окончании работы с сокетом необходимо закрыть соединение и освободить все ресурсы, связанные с дескриптором сокета, с помошью функции closesocket.

int closesocket (SOCKET s); // закрытие сокета

Достаточно легко можно организовать прием данных.

#include <windows.h>

#include <winsock2.h>

# pragma comment (lib, “ws2_32.lib”)

...

SOCKET sock1;

int retcode, SendSize;

SOCKADDR_IN sender;

DWORD Length = 4096;

char *recvbuffer = NULL;

// выделение буфера приема

recvbuffer = (char*) GlobalAlloc (GMEM_FIXED, Length);

if (!recvbuffer) {

printf (“GlobalAlloc () с ошибкой\n”);

exit (1);

}

for (int i = 0; i < 30; i ++) {

SendSize = sizeof (sender);

retcode = recvfrom (sock1, recvbuffer, Length, 0,

(SOCKADDR *)&sender, &SendSize);

if (retcode == SOCKET_ERROR) {

printf (“recvfrom () с ошибкой\n”);

break;

}

else if (retcode == 0) {

break;

}

else {

recvbuffer[retcode] = ‘\0’;

printf (“Строку %s прислал %s\n”,

inet_ntoa(sender.sin_addr), recvbuffer);

}

}

GlobalFree (recvbuffer);

...

Отправка данных будет выглядеть следующим образом.

#include <windows.h>

#include <winsock2.h>

# pragma comment (lib, “ws2_32.lib”)

...

SOCKET sock1;

int retcode;

SOCKADDR_IN receiver;

DWORD Length = 64;

char *sendbuffer = NULL;

// выделение буфера отправки

sendbuffer = (char*)GlobalAlloc (GMEM_FIXED, Length);

if (!sendbuffer) {

printf (“GlobalAlloc () с ошибкой\n”);

exit (1);

}

// Заполнение буфер символами

memset (sendbuffer, ‘+’, Length);

for (int i = 0; i < 30; i ++) {

retcode = sendto (sock1, sendbuffer, Length, 0,

(SOCKADDR *)&receiver, sizeof (receiver));

if (retcode == SOCKET_ERROR) {

printf (“sendto () с ошибкой\n”);

break;

}

else if (retcode == 0) {

break;

}

}

GlobalFree (sendbuffer);

...

Варианты заданий к лабораторной работе №8

Вариант №1

Разработать две программы – сервер и клиент. Клиент отсылает серверу два числа L и U, введенные пользователем, где L – это нижняя граница диапазона, U – верхняя граница диапазона. Сервер принимает значения границ диапазона, вычисляет сумму и произведение чисел от L до U и выводит полученные значения на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №2

Разработать две программы – сервер и клиент. Клиент отсылает серверу введенный пользователем номер числа Фибоначчи. Сервер принимает номер, вычисляет число Фибоначчи с этим номером, по формуле Fi = Fi –1 + Fi –2, F 0 = F 1 = 1 и выводит его на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №3

Разработать две программы – сервер и клиент. Клиент отсылает серверу введенную пользователем строку, хранящую знаковое целое число.
Сервер принимает строку, хранящую знаковое целое число, и выводит на экран строковый эквивалент этого числа прописью (например, ввод «-1211» должен приводить к выводу «минус тысяча двести одиннадцать»). Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №4

Разработать две программы – сервер и клиент. Клиент отсылает серверу введенную пользователем строку, хранящую число со знаком и плавающей точкой. Сервер принимает строку, хранящую число со знаком и плавающей точкой, и выводит на экран строковый эквивалент этого числа прописью (например, ввод «-12.11» должен приводить к выводу «минус двенадцать целых одиннадцать сотых»). Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №5

Разработать две программы – сервер и клиент. Клиент отсылает серверу две строки, введенные пользователем. Сервер принимает две строки.
Далее, если обе строки хранят целые числа со знаком, то на экран выводится сумма чисел, в противном случае – конкатенация двух введенных строк. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №6

Разработать две программы – сервер и клиент. Клиент отсылает серверу элементы двух прямоугольных матриц, введенные пользователем. Сервер принимает две прямоугольных матрицы, а затем выводит на экран их сумму и произведение. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №7

Разработать две программы – сервер и клиент. Клиент отсылает серверу элементы вектора (одномерного целочисленного массива), введенные пользователем. Сервер принимает вектор, упорядочивает его по возрастанию любым из так называемых «улучшенных алгоритмов» сортировки массивов и выводит на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №8

Разработать две программы – сервер и клиент. Клиент отсылает серверу элементы вектора (одномерного массива чисел с плавающей точкой), введенные пользователем. Сервер принимает вектор, упорядочивает его по возрастанию любым из так называемых «улучшенных алгоритмов» сортировки массивов и выводит на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №9

Разработать две программы – сервер и клиент. Клиент отсылает серверу элементы вектора (одномерного массива строк), введенные пользователем. Сервер принимает вектор, упорядочивает его по возрастанию любым из так называемых «улучшенных алгоритмов» сортировки массивов и выводит на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №10

Разработать две программы – сервер и клиент. Клиент отсылает серверу элементы введенной пользователем квадратной матрицы. Сервер принимает матрицу, затем вычисляет сумму элементов, лежащих на главной и побочной диагоналях, и выводит на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №11

Разработать две программы – сервер и клиент. Клиент отсылает серверу элементы введенной пользователем квадратной матрицы. Сервер принимает матрицу, затем вычисляет сумму элементов, не лежащих на главной и побочной диагоналях, и выводит на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №12

Разработать две программы – сервер и клиент. Клиент принимает от пользователя две даты – строки вида ЦЦ.ЦЦ.ЦЦЦЦ, где Ц – это любая цифра из диапазона [0-9] и отсылает серверу. Сервер принимает даты, вычисляет полное количество дней, прошедших между двумя полученными датами, и выводит его на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №13

Разработать две программы – сервер и клиент. Клиент принимает от пользователя два значения времени – строки вида ЦЦ.ЦЦ.ЦЦ, где Ц – это любая цифра из диапазона [0-9], и отсылает серверу. Сервер принимает обе строки, вычисляет полное количество секунд, прошедших между двумя значениями времени, и выводит его на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №14

Разработать две программы – сервер и клиент. Клиент отсылает серверу две строки, введенные пользователем. Сервер принимает, осуществляет поиск вхождения второй строки в первую любым известным методом, кроме прямого (алгоритм Кнута-Мориса-Пратта, алгоритм Боуэра-Мура), и выводит на экран значение индекса элемента первой строки, с которого началось совпадение, или -1 в противном случае. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №15

Разработать две программы – сервер и клиент. Клиент отсылает серверу две строки, введенные пользователем. Сервер принимает две строки, осуществляет поиск количества вхождений второй строки в первую любым известным методом, кроме прямого (алгоритм Кнута-Мориса-Пратта, алгоритм Боуэра-Мура), и выводит на экран полученное значение. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №16

Разработать две программы – сервер и клиент. Клиент принимает от пользователя дату – строку вида ЦЦ.ЦЦ.ЦЦЦЦ, где Ц – это любая цифра из диапазона [0-9,] и отсылает серверу. Сервер принимает дату и выводит на экран число и месяц прописью, а за последними четырьмя – слово «года» (например, ввод «29.02.2008» приводит к выводу «Двадцать девятое февраля 2008 года»). Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №17

Разработать две программы – сервер и клиент. Клиент принимает от пользователя значение времени – строку вида ЦЦ.ЦЦ.ЦЦ, где Ц – это любая цифра из диапазона [0-9] и отсылает серверу. Сервер принимает значение времени и выводит на экран значение часов минут и секунд прописью (например, ввод «12.01.20» приводит к выводу «двенадцать часов одна минута двадцать секунд»). Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №18

Разработать две программы – сервер и клиент. Клиент принимает от пользователя строку из нулей и единиц («битовую строку») и отсылает серверу. Сервер принимает битовую строку, инвертирует ее, выводит на экран значение инвертированной строки, переводит ее в число в десятичный формат и выводит полученное число на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №19

Разработать две программы – сервер и клиент. Клиент принимает от пользователя строку из нулей и единиц («битовую строку») и отсылает серверу. Сервер принимает битовую строку, осуществляет ее реверс (нули заменяются на единицы, а единицы на нули). Полученная строка выводится на экран, затем программа переводит ее в число в десятичном формате и выводит полученное число на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №20

Разработать две программы – сервер и клиент. Клиент отсылает число, введенное пользователем, серверу. Сервер принимает число, вычисляет его факториал по формуле N! = N * (N – 1)!, где 0!= 1, и выводит его на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №21

Разработать две программы – сервер и клиент. Клиент принимает от пользователя квадратную матрицу и отсылает на сервер. Сервер принимает матрицу, осуществляет обход только крайних ее элементов, вычисляет их сумму, и выводит на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №22

Разработать две программы – сервер и клиент. Клиент принимает от пользователя элементы целочисленного вектора (одномерного массива), а также значение ключа для поиска, и отсылает серверу. Сервер принимает вектор и ключ, затем осуществляет поиск элемента по ключу любым известным методом, кроме прямого (двоичный, случайный, золотого сечения), и выводит результат на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №23

Разработать две программы – сервер и клиент. Клиент принимает от пользователя строку символов и отсылает серверу. Сервер принимает строку, осуществляет замену всех латинских букв на их аналоги из кириллицы и выводит результат на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №24

Разработать две программы – сервер и клиент. Клиент принимает от пользователя строку символов и отсылает серверу. Сервер принимает строку, осуществляет смену регистра всех букв и выводит результат на экран. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.

Вариант №25

Разработать две программы – сервер и клиент. Клиент принимает от пользователя беззнаковое целое число и отсылает серверу. Сервер принимает число. Если оно является степенью двойки, то на экран выводится показатель степени, и сообщение «не является степенью двойки» в противном случае. Для взаимодействия воспользоваться механизмом сокетов и протоколом UDP.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: