Протокол АВР (протокол с нумерацией по модулю 2)
Данный протокол является протоколом прикладного уровня и в данной работе использует интерфейс нижележащих уровней (socket).
Описание этого протокола показано на рисунке 4.
N – получение нового сообщения, T – сигнал окончания периода ожидания (тайм-аут), U – обработка полученного сообщения, Di – прием i-го сообщения, Di – передача i-го сообщения, Ai – прием подтверждения о получении i-го сообщения, Ai – передача подтверждения о приходе i-го сообщения, E – прием искаженного сообщения i={0,1}, N, U – внутренние сигналы, не вызывают появление новых сигналов.
Рисунок 4 – Протокол ABP
1.5. Задание к лабораторной работе
1) Отладить программу для установления соединения и передачи тестовой строки символов от клиента к серверу
2) Отладить программу для реализации протокола ABP. Формат данных и подтверждений – произвольный.
1.7. Требования к отчету
Отчет по лабораторной работе должен содержать листинг разработанной программы с комментариями на русском языке.
ПРИЛОЖЕНИЕ
Работа с WinSocket (в Visual C++
Socket (гнездо, разъем) - абстрактное программное понятие, используемое для
обозначения в прикладной программе конечной точки канала связи с
коммуникационной средой, образованной вычислительной сетью. При использовании
протоколов TCP/IP можно говорить, что socket является средством подключения
прикладной программы к порту (см. выше) локального узла сети.
Socket-интерфейс представляет собой просто набор системных вызовов и/или
библиотечных функций языка программирования СИ, разделенных на четыре группы:
Ниже рассматривается подмножество функций socket-интерфейса, достаточное для
написания сетевых приложений, реализующих модель "клиент-сервер" в режиме с
установлением соединения.
Функции локального управления
Функции локального управления используются, главным образом, для выполнения
подготовительных действий, необходимых для организации взаимодействия двух
программ-партнеров. Функции носят такое название, поскольку их выполнение носит
локальный для программы характер.
Создание socket'а
Создание socket'а осуществляется следующим системным вызовом #include
<sys/socket.h> int socket (domain, type, protocol) int domain; int type;
int protocol;
Аргумент domain задает используемый для взаимодействия набор протоколов (вид
коммуникационной области), для стека протоколов TCP/IP он должен иметь
символьное значение AF_INET (определено в sys/socket.h).
Аргумент type задает режим взаимодействия:
- SOCK_STREAM - с установлением соединения;
- SOCK_DGRAM - без установления соединения.
Аргумент protocolзадает конкретный протокол транспортного уровня (из
нескольких возможных в стеке протоколов). Если этот аргумент задан равным 0, то
будет использован протокол "по умолчанию" (TCP для SOCK_STREAM и UDP для
SOCK_DGRAM при использовании комплекта протоколов TCP/IP).
При удачном завершении своей работы данная функция возвращает дескриптор
socket'а - целое неотрицательное число, однозначно его идентифицирующее.
Дескриптор socket'а аналогичен дескриптору файла ОС UNIX.
При обнаружении ошибки в ходе своей работы функция возвращает число "-1".
Связывание socket'а
Для подключения socket'а к коммуникационной среде, образованной
вычислительной сетью, необходимо выполнить системный вызов bind, определяющий в
принятом для сети формате локальный адрес канала связи со средой. В сетях TCP/IP
socket связывается с локальным портом. Системный вызов bind имеет следующий
синтаксис:
#include <sys/socket.h>
#include <netinet/in.h>
int bind (s, addr, addrlen)
int s;
struct sockaddr *addr;
int addrlen;
Аргумент s задает дескриптор связываемого socket'а.
Аргумент addr в общем случае должен указывать на структуру данных, содержащую
локальный адрес, приписываемый socket'у. Для сетей TCP/IP такой структурой
является sockaddr_in.
Аргумент addrlen задает размер (в байтах) структуры данных, указываемой
аргументом addr.
Структура sockaddr_in используется несколькими системными вызовами и
функциями socket-интерфейса и определена в include-файле in.h следующим образом:
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
Поле sin_family определяет используемый формат адреса (набор протоколов), в
нашем случае (для TCP/IP) оно должно иметь значение AF_INET.
Поле sin_addr содержит адрес (номер) узла сети.
Поле sin_port содержит номер порта на узле сети.
Поле sin_zero не используется.
Определение структуры in_addr (из того же include-файла) таково:
struct in_addr {
union {
u_long S_addr; /*
другие (не интересующие нас)
члены объединения */
} S_un;
#define s_addr S_un.S_addr
};
Структура sockaddr_in должна быть полностью заполнена перед выдачей
системного вызова bind. При этом, если поле sin_addr.s_addr имеет значение
INADDR_ANY, то системный вызов будет привязывать к socket'у номер (адрес)
локального узла сети.
В случае успеха bind возвращает 0, в противном случае - "-1".
Функции установления связи
Для установления связи "клиент-сервер" используются системные вызовы listen и
accept (на стороне сервера), а также connect (на стороне клиента). Для
заполнения полей структуры socaddr_in, используемой в вызове connect, обычно
используется библиотечная функция gethostbyname, транслирующая символическое имя
узла сети в его номер (адрес).
Ожидание установления связи
Системный вызов listen выражает желание выдавшей его программы-сервера
ожидать запросы к ней от программ-клиентов и имеет следующий вид:
int listen (s, n)
int s;
int n;
Аргумент s задает дескриптор socket'а, через который программа будет ожидать
запросы к ней от клиентов. Socket должен быть предварительно создан системным
вызовом socketи обеспечен адресом с помощью системного вызова bind.
Аргумент n определяет максимальную длину очереди входящих запросов на
установление связи. Если какой-либо клиент выдаст запрос на установление связи
при полной очереди, то этот запрос будет отвергнут.
Признаком удачного завершения системного вызова listen служит нулевой код
возврата.