+7 (495) 229-0436   shopadmin@itshop.ru 119334, г. Москва, ул. Бардина, д. 4, корп. 3
 
 
Вход
 
 
Каталог
 
 
Подписка на новости
Новости ITShop
Windows 7 и Office: Новости и советы
Обучение и сертификация Microsoft
Вопросы и ответы по MSSQLServer
Delphi - проблемы и решения
Adobe Photoshop: алхимия дизайна
 
Ваш отзыв
Оцените качество магазина ITShop.ru на Яндекс.Маркете. Если вам нравится наш магазин - скажите об этом Google!
 
 
Способы оплаты
 
Курс расчета
 
 1 у.е. = 91.69 руб.
 
 Цены показывать:
 
 
 
 
  
Новости, статьи, акции
 

Интерфейс прикладного программирования Socket API, Часть 5: SCTP

20.07.2012 13:47
Н.Ромоданов

Оригинал: "The Socket API, Part 5: SCTP" 
Автор: Pankaj Tanwar 
Дата публикации: December 29, 2011 
Перевод: Н.Ромоданов 
Дата перевода: июль 2012 г.

В этой статье, посвященной программированию сокетов, мы рассмотрим протокол Stream Control Transmission Protocol (SCTP). Он похож как на протокол TCP, так и на протокол UDP и в нем есть некоторые черты обоих этих протоколов. Он ориентирован на передачу сообщений и гарантирует надежную последовательную их доставку. Протокол SCTP можно использовать сразу в нескольких сетях, т. е. использовать более одного адреса IP с каждой стороны соединения. Поэтому вместо соединения используется ассоциация, т. к. при соединении происходит передача данных между двумя адресами IP, а при ассоциации связь устанавливается между двумя системами, которые могут иметь несколько адресов IP.

Протокол SCTP может поддерживать несколько потоков данных между конечными точками соединения, причем в каждом потоке будет происходить своя собственная надежная последовательная доставка сообщений, так что никакое из потерянныхе сообщение не будет блокировать доставку сообщений в любых других потоках. Протокол SCTP неуязвим для атак типа SYN flooding (переполнение сообщениями SYN), поскольку в нем для установки соединения требуется 4 обмена сообщениями (4-way handshake).

Научную сторону мы обсудим позже, а сейчас перейдем к коду так, как мы обычно это делаем. Но сначала нужно знать типы сокетов протокола SCTP:

  • Сокет типа "один к одному", что соответствует ровно одной ассоциации SCTP (подобно TCP).
  • Сокет типа "один ко многим", когда на сокете могут быть одновременно активны много ассоциаций SCTP (по аналогии с получением датаграмм UDP из нескольких конечных точек).

Сокет типа "один к одному" (также называемый сокетом типа TCP) был разработан для облегчения портирования существующих приложений TCP на SCTP, так что различие между серверами, использующие протоколы TCP и SCTP, не такое уж и большое. Нам просто нужно заменить обращение к функции socket() на обращение к функции socket(AF_INET, SOCK_STREAM и IPPROTO_SCTP), а все остальное остается прежним - вызовы listen(), accept() - для сервера, connect() - для клиента и read() и write() - для обеих программ.

Теперь давайте перейдем к сокету типа "один ко многим" и напишем сервер, использующий несколько потоков, поступающих от клиента.

Во-первых, код для сервера - smtpserver.c:

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
 
 
#define MAX_BUFFER  1024
 
int main()
{
    int sfd, cfd, len, i;
    struct sockaddr_in saddr, caddr;
    struct sctp_initmsg initmsg;
    char buff[INET_ADDRSTRLEN];
    char buffer[MAX_BUFFER+1] = "Message ##\n";
 
 
    sfd = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP );
 
    bzero( (void *)&saddr, sizeof(saddr) );
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl( INADDR_ANY );
    saddr.sin_port = htons(29008);
 
    bind( sfd, (struct sockaddr *)&saddr, sizeof(saddr) );
 
/* Maximum of 3 streams will be available per socket */
    memset( &initmsg, 0, sizeof(initmsg) );
    initmsg.sinit_num_ostreams = 3;
    initmsg.sinit_max_instreams = 3;
    initmsg.sinit_max_attempts = 2;
    setsockopt( sfd, IPPROTO_SCTP, SCTP_INITMSG, 
            &initmsg, sizeof(initmsg) );
 
    listen( sfd, 5 );
 
    for(;;) {
        printf("Server Running\n");
 
        len=sizeof(caddr);
        cfd=accept(sfd, (struct sockaddr *)&caddr, &len);
         
        printf("Connected to %s\n",
            inet_ntop(AF_INET, &caddr.sin_addr, buff,
            sizeof(buff)));
 
         
        for(i=0; i< 3; i++) {
/* Changing 9th character the character after # in the message buffer */
            buffer[9] = '1'+i;
 
            sctp_sendmsg( cfd, (void *)buffer, (size_t)strlen(buffer),
                    NULL, 0, 0, 0, i /* stream */, 0, 0 );
            printf("Sent: %s\n", buffer);
        }
 
        close( cfd );
    }
    return 0;
}

А вот код клиента sctpclient.c:

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
 
#define MAX_BUFFER  1024
 
int main(int argc, char **argv)
{
    int cfd, i, flags;
    struct sockaddr_in saddr;
    struct sctp_sndrcvinfo sndrcvinfo;
    struct sctp_event_subscribe events;
    struct sctp_initmsg initmsg;
    char buffer[MAX_BUFFER+1];
 
    if(argc!=2) {
        printf("Usage: %s ipaddress\n", argv[0]);
    return -1;
    }
 
    cfd = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP );
 
/* Specify that a maximum of 3 streams will be available per socket */
    memset( &initmsg, 0, sizeof(initmsg) );
    initmsg.sinit_num_ostreams = 3;
    initmsg.sinit_max_instreams = 3;
    initmsg.sinit_max_attempts = 2;
    setsockopt( cfd, IPPROTO_SCTP, SCTP_INITMSG,
            &initmsg, sizeof(initmsg) );
 
    bzero( (void *)&saddr, sizeof(saddr) );
    saddr.sin_family = AF_INET;
    inet_pton(AF_INET, argv[1], &saddr.sin_addr);
    saddr.sin_port = htons(29008);
     
    connect( cfd, (struct sockaddr *)&saddr, sizeof(saddr) );
 
    memset( (void *)&events, 0, sizeof(events) );
    events.sctp_data_io_event = 1;
    setsockopt( cfd, SOL_SCTP, SCTP_EVENTS,
        (const void *)&events, sizeof(events) );
 
     
/* Sending three messages on different streams */
 
    for (i=0; i<3; i++) {
        bzero( (void *)&buffer, sizeof(buffer) );
 
        sctp_recvmsg( cfd, (void *)buffer, sizeof(buffer),
                        (struct sockaddr *)NULL, 0, &sndrcvinfo, &flags );
 
        printf("Received following data on stream %d\n\n%s\n",
            sndrcvinfo.sinfo_stream, buffer);
 
    }
 
    close(cfd);
 
    return 0;
}

Сервер посылает три сообщения в трех различных потоках, а клиент просто принимает сообщения и выдает их на экран (рис. 1 и 2).

Рис.1: Данные, выдаваемые сервером

Рис.2: Данные, выдаваемые клиентом

Различие лишь в том, что мы создаем итеративный сервер, похожий на сервер для UDP, но здесь мы должны использовать вызов accept(). Клиент делает обратное - получает сообщения, идущие от сервера к клиенту. Теперь давайте попробуем разобраться в функциях, которые мы использовали:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/sctp.h>
 
int sctp_sendmsg (int sd, const void *msg, size_t len,
    struct sockaddr *to, socklen_t tolen, uint32_t ppid, uint32_t
    flags, uint16_t stream_no, uint32_t timetolive, uint32_t context);

Мы пользуемся этой функцией для отправки сообщений из сокета когда используем расширенные возможности протокола SCTP. Первый аргумент в функции -sd, дескриптор сокета, из которого посылается сообщение msg, имеющее длину len. В четвертом аргументе указывается адрес назначения - tolen задает длину адреса, а stream_no определяет номер потока, в который посылается данное собщение. Параметр flags используется для передачи некоторых настроек принимающей стороне. Вы можете посмотреть страницы руководства для sctp_sendmsg().

В параметре timetolive указывется время в миллисекундах, после которого сообщение можно не отправлять, если оно еще не отправлено; ноль указывает, что тайм-аут не установлен. Context является значением, которое в случае, если при отправке сообщения произошла ошибка, передается на верхний уровень вместе с недоставленным сообщением. В случае успеха функция возвращает количество отправленных байтов, или -1 - в случае ошибки.

Далее идет функция stcp_recvmsg():

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/sctp.h>
 
int sctp_recvmsg(int sd, void * msg, size_t len, struct
    sockaddr * from, socklen_t * fromlen, struct sctp_sndrcvinfo
    * sinfo, int * msg_flags);

Эта функция выполняет действия, обратные действию функции sctp_sendmsg, и используется для получения сообщений. Параметры аналогичны. Сокет sdпринимает сообщение msg, имеющее длину len, из адреса *from, длина которого *fromlen, а *sinfo является указателем на адрес, который будет заполнен при получении сообщения. mag_flags является указателем на целое с флагами, похожими на MSG_NOTIFICATION или MSG_EOR. Функция возвращает количество полученных байтов или -1 - при ошибке.

#include <sys/types.h>
#include <sys/socket.h>
 
int setsockopt(int sockfd, int level, int optname,
                      const void *optval, socklen_t optlen);

Эта функция используется для установки параметров сокета sockfd. Следующим аргументом является тот уровень level, на котором используется устанавливаемый параметр. Чтобы манипулировать параметрами на уровне сокетов API, значение level должно быть определено как SOL_SOCKET. Параметр optname и все остальные указываемые параметры передаются в неинтерпретируемом виде в соответствующий модуль протокола для их последующей там интерпретации. Параметры level и optname определены в sys/sockets.h. Аргументы optval и optlen используются для доступа к значениям параметров вsetsockopt(), которые хранятся в структуре. Параметры устанавливаются на сервере следующим образом:

initmsg.sinit_num_ostreams = 3;
initmsg.sinit_max_instreams = 3;
initmsg.sinit_max_attempts = 2;

Здесь в первых двух строках указывается, что нам доступны три входных и три выходных потока, а максимальное количество делаемых попыток будет равно двум. Те же самые параметры задаются в клиентской программе. Другие параметры устанавливаются для конкретных событий. Эта структура будет заполняться тогда , как будет возникать событие "сообщение принято", и наша программа будет получать уведомление. Противоположной ей функцией будет функция getsockopts()(смотрите подсказку в справочных страницах). Остальная часть кода проста для понимания.

Теперь скомпилируем и запустим программу; убедитесь, что вы установили пакет sctp-tools, т.к. вам нужен заголовок тsctp.h из netinet/. Для компиляции используйте команду gcc sctpserver.c -lsctp -o server && gcc sctpclient.c -lsctp -o client; а для запуска используйте следующий код:

$ ./server &
$  ./client

На данный момент я подвожу итог данной серии, но буду периодически расширять эту тему.

Ссылки по теме

  
Помощь
Задать вопрос
 программы
 обучение
 экзамены
 компьютеры
Бесплатный звонок
ICQ-консультанты
Skype-консультанты

Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта
 
Бестселлеры
Курсы обучения "Atlassian JIRA - система управления проектами и задачами на предприятии"
Microsoft Windows 10 Профессиональная 32-bit/64-bit. Все языки. Электронный ключ
Microsoft Office для Дома и Учебы 2019. Все языки. Электронный ключ
Курс "Oracle. Программирование на SQL и PL/SQL"
Курс "Основы TOGAF® 9"
Microsoft Office 365 Персональный 32-bit/x64. 1 ПК/MAC + 1 Планшет + 1 Телефон. Все языки. Подписка на 1 год. Электронный ключ
Курс "Нотация BPMN 2.0. Ее использование для моделирования бизнес-процессов и их регламентации"
 

О нас
Интернет-магазин ITShop.ru предлагает широкий спектр услуг информационных технологий и ПО.

На протяжении многих лет интернет-магазин предлагает товары и услуги, ориентированные на бизнес-пользователей и специалистов по информационным технологиям.

Хорошие отзывы постоянных клиентов и высокий уровень специалистов позволяет получить наивысший результат при совместной работе.

В нашем магазине вы можете приобрести лицензионное ПО выбрав необходимое из широкого спектра и ассортимента по самым доступным ценам. Наши менеджеры любезно помогут определиться с выбором ПО, которое необходимо именно вам. Также мы проводим учебные курсы. Мы приглашаем к сотрудничеству учебные центры, организаторов семинаров и бизнес-тренингов, преподавателей. Сфера сотрудничества - продвижение бизнес-тренингов и курсов обучения по информационным технологиям.



 

О нас

 
Главная
Каталог
Новинки
Акции
Вакансии
 

Помощь

 
Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта
 

Способы оплаты

 

Проекты Interface Ltd.

 
Interface.ru   ITShop.ru   Interface.ru/training   Olap.ru   ITnews.ru  
 

119334, г. Москва, ул. Бардина, д. 4, корп. 3
+7 (495) 229-0436   shopadmin@itshop.ru
Проверить аттестат
© ООО "Interface Ltd."
Продаем программное обеспечение с 1990 года