ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

         
     
    Програмуємо під IIS на Visual C ++
         

     

    Інформатика, програмування

    Програмуємо під IIS на Visual C + +

    Однією з поширених завдань адміністрування web-сайтів є аналіз log-файлів і збір даних з них. Поговоримо про цю задачі на прикладі IIS 5.0 (Internet Information Service). У зв'язку з тим, що даний HTTP сервер підтримує кілька форматів таких файлів (формат W3C, формат NCSA, а також свій формат IIS), аналіз log-файлів перетворюється на досить трудомістку задачу. Крім того для формату W3C список полів може конфігуруватися, що завдання не полегшує.

    Але на щастя разом з IIS 5.0 у складі інших компонентів, поставляється компонент MSWC.IISLog, що призначений для одержання даних з log-файлів і надає для цієї мети інтерфейс ILogScripting. Знаходиться він у файлі% windir% system32inetsrvlogscrpt.dll. З допомогою цього інтерфейсу можна читати дані з log-файлу, записувати прочитані дані в інший файл.

    Перед тим як почати роботу з будь-якими log-файлом, його потрібно відкрити. Для цього служить метод OpenLogFile:

    HRESULT OpenLogFile ([in] BSTR szLogFileName,

    [in] IOMode Mode,

    [in] BSTR szServiceName,

    [in] long iServiceInstance,

    [in] BSTR szOutputLogFileFormat),

    де в параметрі szLogFileName задається повний шлях до файлу; параметр Mode може приймати наступні значення:

    ForReading - файл буде відкрито для читання

    ForWriting - файл буде відкритий для запису;

    в параметрі szServiceName задається назва служби, якої був створений даний файл (наприклад "W3SVC"); парметр iServiceInstance вказує номер примірника сервера даної служби (напр. 1); в параметрі szOutputLogFileFormat задається назва формату, в якому будуть читатися чи записуватися дані (наприклад "W3C"). Якщо метод виконався успішно то повертається 0.

    Для читання даних з файлу служить метод ReadLogRecord:

    HRESULT ReadLogRecord (),

    який читає рядок з поточної файлової позиції і переміщує позиціонер файлу далі. Ми можемо отримати ці дані у вигляді значень конкретних полів за допомогою безлічі методів, які повертають ці значення:        

    get_DateTime         

    Відображення дати та часу   за Гринвічем (GMT)             

    get_ServiceName         

    Відображення імені служби             

    get_ServerName         

    Відображення імені сервера             

    get_ClientIP         

    Відображення імені вузла   клієнта             

    get_UserName         

    Відображення імені користувача             

    get_ServerIP         

    Відображення IP-адреси сервера             

    get_Method         

    Відображення типу операції             

    get_URIStem         

    Відображення адреси URL             

    get_URIQuery         

    Відображення всіх параметрів, що передаються з   запитом             

    get_TimeTaken         

    Відображення загального часу   обробки             

    get_BytesSent         

    Відображення числа переданих байтів             

    get_BytesReceived         

    Відображення числа отриманих байтів             

    get_Win32Status         

    Відображення коду стану Win32             

    get_ProtocolStatus         

    Відображення стану протоколу             

    get_ServerPort         

    Відображення номера порту             

    get_ProtocolVersion         

    Відображення рядка версії             

    get_UserAgent         

    Відображення рядка агента користувача             

    get_Cookie         

    Відображення імені Cookie клієнта             

    get_Referer         

    Відображення сторінки джерела посилання             

    get_CustomFields         

    Відображення масиву   спеціальних заголовків     

    Всі ці методи мають один формат: HRESULT get_MethodName (VARIANT * pValue). У параметрі pValue буде повернуто який нас цікавить значення. Якщо значення запитуваної параметра дорівнює "-", то тип pValue буде VT_EMPTY. Якщо ж з якихось причин параметр не буде знайдено в log-файлі (напр. параметр вимкнено, або поточний рядок - незначущий), то тип pValue буде VT_NULL.

    Для того, щоб ми сильно не захопилися існує метод AtEndOfLog, який подібно до звичного feof повертає (або не повертає :)) Ознака досягнення кінця файлу і виглядає приблизно так:

    HRESULT AtEndOfLog ([out, retval] VARIANT_BOOL * pfEndOfRead)

    У параметрі pfEndOfRead, власне, і повертається що нас цікавить ознака, що дозволяє нам все таки коли-небудь завершити обробку log-файлу.

    Крім усього цього є ще метод WriteLogRecord, який дозволяє записувати дані, отримані з одного log-файла в інший. Формат його наступний:

    HRESULT WriteLogRecord ([in] ILogScripting * pILogScripting),

    де

    pILogScripting - це покажчик на екземпляр ILogScripting, в якому містяться прочитані дані. Цей метод схожий на ReadLogRecord тим, що записує в файл один рядок (нагадаю, що ReadLogRecord читає один рядок).

    Для закриття відкритих файлів служить метод CloseLogFiles:

    HRESULT CloseLogFiles ([in] IOMode Mode),

    в якому параметр Mode може приймати наступні значення:

    ForReading - будуть закриті файли, відкриті для читання

    ForWriting - будуть закриті файли, відкриті для запису

    AllOpenFiles - будуть закриті всі відкриті файли

    Щоб доступитися до компоненту MSWC.IISLog з C + + треба мати. h файл, що описує інтерфейс ILogScripting. Зробити його нам допоможе утиліта OLEViewer, яка входить до складу Visual Studio. У меню "File" цієї утиліти виберемо пункт "View TypeLib" і зазначимо файл logscrpt.dll (природно повний шлях до нього). У новому вікні відкриється бібліотека типів нашого об'єкта, яку збережено в якості. idl файлу.

    Для цього в меню "File" виберемо пункт "Save as", вкажемо тип файлу "idl", і збережемо його на якусь місце (наприклад туди, де знаходиться проект), наприклад, назвавши його "logscrpt.idl". Все б добре, та тільки в новоспеченому фото доведеться зробити косметичні зміни. По-перше в самий початок файлу треба вставити наступні рядки:

    cpp_quote ( "DEFINE_GUID (CLSID_LogScripting, 0x26B9ED02, 0xA3D8, 0x11D1, 0x8B, 0x9C, 0x08, 0x00, 0x09, 0xDC, 0xC2, 0xFA );")

    cpp_quote ( "DEFINE_GUID (IID_ILogScripting, 0x26B9ECFF, 0xA3D8, 0x11D1, 0x8B, 0x9C, 0x08, 0x00, 0x09, 0xDC, 0xC2, 0xFA );")

    По-друге рядки

    typedef enum (

    ForReading = 1,

    ForWriting = 2,

    AllOpenFiles = 32

    ) IOMode;

    треба перенести так, щоб вони перебували до визначення ILogScripting інтерфейсу.

    Тепер залишилося тільки згенерувати файл logscrpt.h з допомогою команди midl.exe logscrpt.idl/h logscrpt.h (перевірте шлях до компілятору midl).

    На закінчення наведу приклад програми роботи з інтерфейсом, яка отримує в якості параметрів командного рядка шлях до log-файлу, назва служби, назву формату файлу, номер примірника сервера і видає на екран список всіх URL адрес, до яких були зафіксовані звернення в цьому файлі. Ось приклад виклику цієї програми:

    logging.exe d: logsw3svc2ex01060515.log W3SVC W3C 2

    # include

    # include

    # include

    # include

    # include "logscrpt.h"

    # define SOME_ERROR (lpszErrorText, nErrorNum)

    printf ( "% s:% X

    ", lpszErrorText, nErrorNum);

    throw nErrorNum;

    int main (int argc, char * argv [])

    (

    HRESULT hres;

    VARIANT vParam;

    short nEndOfFile;

    _bstr_t bstrLogFile;

    _bstr_t bstrServiceName;

    _bstr_t bstrLogFormat;

    long nServerInstance;

    _bstr_t bstrUriStem;

    // перевірка наявності параметрів

    if (argc <5)

    (

    printf ( "Usage: % s LogFileName ServiceNa

    me LogFormatName ServerInstance

    ", argv [0 ]);

    return 0;

    )

    // отримуємо параметри з командної строчки

    try (

    bstrLogFile = argv [1];

    bstrServiceName = argv [2];

    bstrLogFormat = argv [3];

    if (! (nServerInstance = atol (argv [4 ])))

    // екземпляр сервера не може бути 0

    nServerInstance = 1;

    )

    catch (...) (

    printf ( "Something wrong in parameters!

    ");

    return 0;

    )

    // це буде посилання на інтерфейс

    ILogScripting * pLogScripting = NULL;

    try (

    // ініціалізіруем COM

    if (! SUCCEEDED (hres = CoInitialize (NULL )))

    (

    SOME_ERROR ( "CoInitialize error ", hres);

    )

    // тепер створимо екзепляр інтерфейсу

    if (! SUCCEEDED (hres = CoCreateInstance (CLSID_LogScripting,

    NULL, CLSCTX_ALL, IID_ILogScripting,

    (void **) & pLogScripting )))

    (

    SOME_ERROR ( "CoCreateInstance error ", hres);

    )

    // відкриваємо log-файл bstrLogFile для читання, вказуючи, що цей

    // фото відноситься до перших примірників сервера служби W3SVC, а//

    // формат у нього W3C

    if (! SUCCEEDED (hres =

    pLogScripting-OpenLogFile (BSTR (bstrLogFile), ForReading,

    BSTR (bstrServiceName), 1, BSTR (bstrLogFormat ))))

    (

    SOME_ERROR ( "OpenLogFile error ", hres);

    )

    // тепер можна приступити до аналізу вмісту файлу

    for (;;) (

    // перевіримо на досягнення кінця файлу

    if (! SUCCEEDED (hres =

    pLogScripting-AtEndOfLog (& nEndOfFile )))

    (

    SOME_ERROR ( "AtEndOfLog error", hres);

    )

    if (nEndOfFile)

    // щасливо виходимо

    break;

    // читаємо такий запис файлу

    if (! SUCCEEDED (hres = pLogScripting-ReadLogRecord ()))

    (

    SOME_ERROR ( "ReadLogRecord error", hres);

    )

    // отримуємо з неї параметр адреса URL

    if (! SUCCEEDED (hres = pLogScripting-get_URIStem (& vParam )))

    (

    SOME_ERROR ( "ReadLogRecord error", hres);

    )

    if (vParam.vt == VT_BSTR)

    (

    // якщо параметр не порожній роздрукувати його на екрані

    bstrUriStem = vParam.bstrVal;

    printf ( "Uri-stem:% s

    ", LPSTR (bstrUriStem ));

    )

    )

    // закриваємо файл

    if (! SUCCEEDED (hres = pLogScripting-CloseLogFiles (ForReading )))

    (

    SOME_ERROR ( "CloseLogFiles error ", hres);

    )

    )

    catch (...) ()

    // останні дії по деініціалізацію

    if (pLogScripting! = NULL)

    pLogScripting-Release ();

    CoUninitialize ();

    return hres;

    )

    Dima Mukalov

    Список літератури

    Для підготовки даної роботи були використані матеріали з сайту http://www.realcoding.net/

    Робота з WinSocket в Visual C + +

    Socket (гніздо, роз'єм) - абстрактне програмне поняття, що використовується для позначення в прикладній програмі кінцевої точки каналу зв'язку з комунікаційним середовищем, утвореної обчислювальною мережею. При використанні протоколів TCP/IP можна говорити, що socket є засобом підключення прикладної програми до порту (див. вище) локального вузла мережі.

    Socket-інтерфейс являє собою просто набір системних викликів та/або бібліотечних функцій мови програмування СІ, розділених на чотири групи:

    Нижче розглядається підмножина функцій socket-інтерфейсу, достатню для написання мережевих програм, що реалізують модель "клієнт-сервер" в режимі з встановленням з'єднання.

    1. Опції локального управління

    Опції локального управління використовуються, головним чином, для виконання підготовчих дій, необхідних для організації взаємодії двох програм-партнерів. Опції носять таку назву, оскільки їх виконання носить локальний для програми характер.

    1.1 Створення socket'а

    Створення socket'а здійснюється наступним системним викликом # include 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".

    1.2. Зв'язування socket'а

    Для підключення socket'а до комунікаційне середовище, утвореної обчислювальної мережі, необхідно виконати системний виклик bind, визначальними у прийнятому для мережі форматі локальний адресу каналу зв'язку з середовищем. У мережах TCP/IP socket зв'язується з локальним портом. Системний виклик bind має наступний синтаксис:

    # include

    # include

    # include

    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 наступним чином:

    struct sockaddr_in (

    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".

    2. Функції встановлення зв'язку

    Для встановлення зв'язку "клієнт-сервер" використовуються системні виклики listen і accept (на стороні сервера), а також connect (на стороні клієнта). Для заповнення полів структури socaddr_in, використовуваної у виклику connect, звичайно використовується бібліотечна функція gethostbyname, що транслює символічне ім'я вузла мережі в його номер (адреса).

    2.1. Очікування встановлення зв'язку

    Системний виклик listen висловлює бажання видала його програми-сервера очікувати запити до неї від програм-клієнтів і має наступний вигляд:

    # include

    int listen (s, n)

    int s;

    int n;

    Аргумент s задає дескриптор socket'а, через який програма буде очікувати запити до неї від клієнтів. Socket повинен бути попередньо створений системним викликом socketі забезпечений адресою з допомогою системного виклику bind.

    Аргумент n визначає максимальну довжину черги вхідних запитів на встановлення зв'язку. Якщо будь-який клієнт видасть запит на встановлення зв'язку при повній черзі, то цей запит буде відкинутий.

    Ознакою вдалого завершення системного виклику listen служить нульовий код повернення.

    2.2. Запит на встановлення з'єднання

    Для звернення програми-клієнта до сервера з запитом на встановлення логічної з'єднання використовується системний виклик connect, має такий вигляд # include # include # include int connect (s, addr, addrlen) int s; struct sockaddr_in * addr; int addrlen;

    Аргумент s задає дескриптор socket'а, через який програма звертається до сервера з запитом на з'єднання. Socket повинен бути попередньо створений системним викликом socketі забезпечений адресою з допомогою системного виклику bind.

    Аргумент addr повинен вказувати на структуру даних, містить адресу, приписаний socket'у програми-сервера, до якої робиться запит на з'єднання. Для мереж TCP/IP такою структурою є sockaddr_in. Для формування значень полів структури sockaddr_in зручно використовувати функцію gethostbyname.

    Аргумент addrlen задає розмір (в байтах) структури даних, що вказується аргументом addr.

    Для того, щоб запит на з'єднання був успішним, необхідно, принаймні, щоб програма-сервер виконала до цього моменту системний виклик listen для socket'а з вказаною адресою.

    При успішному виконанні запиту системний виклик connect повертає 0, в іншому випадку - "-1" (встановлюючи код причини неуспіху в глобальній змінній errno).

    Примітка. Якщо до моменту виконання connect використовуваний ним socket не був прив'язаний до адреси за допомогою bind, то така прив'язка буде виконана автоматично.

    Примітка. У режимі взаємодії без встановлення з'єднання необхідності у виконанні системного виклику connect немає. Однак, його виконання в такому режимі не є помилкою - просто міняється зміст виконуваних при цьому дій: встановлюється адреса "за замовчуванням" для всіх наступних посилок дейтаграм.

    2.3. Прийом запиту на встановлення зв'язку

    Для прийому запитів від програм-клієнтів на встановлення зв'язку в програмах-серверах використовується системний виклик accept, має такий вигляд:

    # include

    # include

    int accept (s, addr, p_addrlen)

    int s;

    struct sockaddr_in * addr;

    int * p_addrlen;

    Аргумент s задає дескриптор socket'а, через який програма-сервер отримала запит на з'єднання (за допомогою системного запиту listen).

    Аргумент addr повинен вказувати на область пам'яті, розмір якої дозволяв би розмістити в ній структуру даних, що містить адресу socket'а програми-клієнта, яка зробила запит на з'єднання. Ніякої ініціалізації цій області не потрібно.

    Аргумент p_addrlen повинен вказувати на область пам'яті у вигляді цілого числа, що задає розмір (в байтах) області пам'яті, що вказується аргументом addr.

    Системний виклик accept витягує з черги, організованою системним викликом listen, перший запит на з'єднання і повертає дескриптор нового (автоматично створеного) socket'а з тими ж властивості, що й socket, що задається аргументом s. Цей новий дескриптор необхідно використовувати у всіх подальших операціях обміну даними.

    Крім того після у?? ачного завершення accept:

    область пам'яті, що вказується аргументом addr, буде містити структуру даних (для мереж TCP/IP це sockaddr_in), що описує адреса socket'а програми-клієнта, через який вона зробила свій запит на з'єднання;

    ціле число, на яке вказує аргумент p_addrlen, дорівнюватиме розміру цієї структури даних.

    Якщо чергу запитів на момент виконання accept порожня, то програма переходить в стан очікування надходження запитів від клієнтів на невизначений час (хоча така поведінка accept можна і змінити).

    Ознакою невдалого завершення accept служить негативне повернене значення (дескриптор socket'а негативним бути не може).

    Примітка. Системний виклик accept використовується в програмах-серверах, що функціонують тільки в режимі з встановленням з'єднання.

    2.4. Формування адреси вузла мережі

    Для отримання адреси вузла мережі TCP/IP за його символічному імені використовується бібліотечна функція

    # include

    # include

    struct hostent * gethostbyname (name)

    char * name;

    Аргумент name задає адреса послідовності літер, утворять символічне ім'я вузла мережі.

    При успішному завершенні функція повертає вказівник на структуру hostent, визначену у include-файлі netdb.h і має наступний вид struct hostent (char * h_name; char ** h_aliases; int h_addrtype; int h_lenght; char * h_addr;);

    Поле h_name вказує на офіційне (основне) ім'я вузла.

    Поле h_aliases вказує на список додаткових імен вузла (синонімів), якщо вони є.

    Поле h_addrtype містить ідентифікатор використовується набору протоколів, для мереж TCP/IP це поле буде мати значення AF_INET.

    Поле h_lenght містить довжину адреси вузла.

    Поле h_addr вказує на область пам'яті, що містить адреса вузла в тому вигляді, в якому його використовують системні виклики та функції socket-інтерфейсу.

    Приклад звернення до функції gethostbyname для отримання адреси віддаленого вузла в програмі-клієнті, що використовує системний виклик connect для формування запиту на підтримання зв'язку з програмою-сервером на цьому сайті, розглядається нижче.

    3. Функції обміну даними

    У режимі зі встановленням логічного з'єднання після вдалого виконання пари взаємопов'язаних системних викликів connect (у клієнта) і accept (в сервер) стає можливим обмін даними.

    Цей обмін може бути реалізований звичайними системними викликами read і write, що використовуються для роботи з файлами (при цьому замість дескрипторів файлів у них задаються дескриптори socket'ов).

    Крім того можуть бути додатково використані системні виклики send і recv, спеціально орієнтовані на роботу з socket'амі.

    Примітка. Для обміну даними в режимі без встановлення логічного з'єднання використовуються, як правило, системні виклики sendtoі recvfrom. Sendto дозволяє специфікувати разом з передаваними даними (складовими дейтаграму) адреса їх одержувача. Recvfrom одночасно з доставкою даних одержувачу інформує його і про адресу відправника.

    3.1. Здійснення даних

    Щоб здійснити даних партнеру з мережевого взаємодії використовується системний виклик send, що має такий вигляд

    # include

    # include

    int send (s, buf, len, flags)

    int s;

    char * buf;

    int len;

    int flags;

    Аргумент s задає дескриптор socket'а, через який надсилаються дані.

    Аргумент buf вказує на область пам'яті, що містить передані дані.

    Аргумент len задає довжину (у байтах) передаються даних.

    Аргумент flags модифікує виконання системного виклику send. При нульовому значенні цього аргументу виклик send повністю аналогічний системного виклику write.

    При успішному завершенні send повертає кількість переданих з області, зазначеної аргументом buf, байт даних. Якщо канал даних, який визначається дескриптором s, виявляється "переповненим", то send переводить програму в стан очікування до моменту його звільнення.

    3.2. Отримання даних

    Для отримання даних від партнера по мережному взаємодії використовується системний виклик recv, що має такий вигляд

    # include

    # include

    int recv (s, buf, len, flags)

    int s;

    char * buf;

    int len;

    int flags;

    Аргумент s задає дескриптор socket'а, через який приймаються дані.

    Аргумент buf вказує на область пам'яті, призначену для розміщення прийнятих даних.

    Аргумент len задає довжину (у байтах) цієї області.

    Аргумент flags модифікує виконання системного виклику recv. При нульовому значенні цього аргументу виклик recv повністю аналогічний системного виклику read.

    При успішному завершенні recv повертає кількість прийнятих в область, зазначену аргументом buf, байт даних. Якщо канал даних, обумовлений дескриптором s, виявляється "порожнім", то recv переводить програму в стан очікування до моменту появи в ньому даних.

    4. Опції закриття зв'язку

    Для закриття зв'язку з партнером по мережному взаємодії використовуються системні виклики close і shutdown.

    4.1. Виклик close

    Для закриття раніше створеного socket'а використовується звичайний системний виклик close, що застосовується в ОС UNIX для закриття раніше відкритих файлів і має такий вигляд

    int close (s)

    int s;

    Аргумент s задає дескриптор раніше створеного socket'а.

    Проте в режимі з встановленням логічного з'єднання (що забезпечує, як правило, надійну доставку даних) внутрішньосистемні механізми обміну будуть намагатися передати/прийняти дані, що залишилися в каналі передачі на момент закриття socket'а. Це може тривати значний інтервал часу, неприйнятний для деяких додатків. У такій ситуації необхідно використовувати описуваний далі системний виклик shutdown.

    4.2. Скидання буферізованние даних

    Для "екстреного" закриття зв'язку з партнером (шляхом "скидання" ще не переданих даних) використовується системний виклик shutdown, що виконується перед close і має такий вигляд

    int shutdown (s, how)

    int s;

    int how;

    Аргумент s задає дескриптор раніше створеного socket'а.

    Аргумент how задає дії, що виконуються при очищенні системних буферів socket'а:

    0 - скинути і далі не брати дані для читання з socket'а;

    1 - скинути і далі не відправляти дані для посилки через socket;

    2 - скинути всі дані, передані через socket в будь-якому напрямку.

    5. Приклад використання socket-інтерфейсу

    У цьому розділі розглядається використання socket-інтерфейсу в режимі взаємодії зі встановленням логічного з'єднання на дуже простому прикладі взаємодії двох програм (сервера і клієнта), що функціонують у різних вузлах мережі TCP/IP.

    Змістовна частина програм примітивна:

    сервер, прийнявши запит на з'єднання, передає клієнту питання "Who are you?";

    клієнт, отримавши питання, виводить його в стандартний висновок і направляє серверу відповідь "I am your client" і завершує на цьому свою роботу;

    сервер виводить у стандартний вивід відповідь клієнта, закриває з ним зв'язок і переходить в стан очікування наступного запиту до нього.

    Примітка. Пропоновані нижче тексти програм призначені тільки для ілюстрації логіки взаємодії програм через мережу, тому в них відсутні такі атрибути програм, призначених для практичного застосування, як обробка кодів повернення системних викликів і функцій, аналіз кодів помилок в глобальній змінній errno, реакція на асинхронні події і т.п.

    5.1. Програма-сервер

    Текст програми-сервера на мові програмування СІ виглядає наступним чином

    1 # include

    2 # include

    3 # include

    4 # include

    5 # include

    6 # define SRV_PORT 1234

    7 # define BUF_SIZE 64

    8 # define TXT_QUEST "Who are you? n "

    9 main () (

    10 int s, s_new;

    11 int from_len;

    12 char buf [BUF_SIZE];

    13 struct sockaddr_in sin, from_sin;

    14 s = socket (AF_INET, SOCK_STREAM, 0);

    15 memset ((char *) & sin,'', sizeof (sin));

    16 sin.sin_family = AF_INET;

    17 sin.sin_addr.s_addr = INADDR_ANY;

    18 sin.sin_port = SRV_PORT;

    19 bind (s, (struct sockaddr *) & sin, sizeof (sin));

    20 listen (s, 3);

    21 while (1) (

    22 from_len = sizeof (from_sin);

    23 s_new = accept (s, & from_sin, & from_len);

    24 write (s_new, TXT_QUEST, sizeof (TXT_QUEST));

    25 from_len = read (s_new, buf, BUF_SIZE);

    26 write (1, buf, from_len);

    27 shutdown (s_new, 0);

    28 close (s_new);

    29);

    30)

    Рядки 1 ... 5 описують включаються файли, що містять визначення для всіх необхідних структур даних і символічних констант.

    Рядок 6 приписує цілочисельний константі 1234 символічне ім'я SRV_PORT. Надалі ця константа буде використана в як номер порту сервера. Значення цієї константи має бути відомо і програми-клієнта.

    Рядок 7 приписує цілочисельний константі 64 символічне ім'я BUF_SIZE. Ця константа буде визначати розмір буфера, використовуваного для розміщення приймаються від клієнта даних.

    Рядок 8 приписує послідовності символів, складових текст питання клієнту, символічне ім'я TXT_QUEST. Останнім символом у послідовності є символ переходу на новий рядок 'n'. Зроблено це для спрощення перегляду тексту питання на стороні клієнта.

    У рядку 14 створюється (відкривається) socket для організації режиму взаємодії зі встановленням логічного з'єднання (SOCK_STREAM) у мережі TCP/IP (AF_INET), при виборі протоколу транспортного рівня використовується протокол "за умовчанням" (0).

    У рядках 15 ... 18 спочатку обнуляється структура даних sin, а потім заповнюються її окремі поля. Використання константи INADDR_ANY спрощує текст програми, позбавляючи від необхідності використовувати функцію gethostbyname для отримання адреси локального вузла, на якому запускається сервер.

    Рядок 19 за допомогою системного виклику bind прив'язує socket, що задається дескриптором s, до порту з номером SRV_PORT на локальному вузлі. Bind завершиться успішно за умови, що в момент його виконання на тому ж сайті вже не функціонує програма, що використовує цей номер порту.

    Рядок 20 за допомогою системного виклику listen організовує чергу на три входять до сервера запиту на з'єднання.

    Рядок 21 служить заголовком нескінченного циклу обслуговування запитів від клієнтів.

    На рядку 23, що містить системний виклик accept, виконання програми призупиняється на невизначений час, якщо чергу запитів до сервера на встановлення зв'язку виявляється порожня. При появі такого запиту accept успішно завершується, повертаючи в змінної s_new дескриптор socket'а для обміну інформацією з клієнтом.

    У рядку 24 сервер з допомогою системного виклику write відправляє клієнту питання.

    У рядку 25 за допомогою системного виклику read читається відповідь клієнта.

    У рядку 26 відповідь направляється у стандартний висновок, що має дескриптор файлу номер 1. Так як рядок відповіді містить в собі символ переходу на новий рядок, то текст відповіді буде розміщений на окремому рядку дисплея.

    Рядок 27 містить системний висновок shutdown, забезпечує очищення системних буферів socket'а, що містять дані для читання ( "зайві" дані можуть там опинитися в результаті невірної роботи клієнта).

    У рядку 28 закривається (вилучається) socket, використаний для обміну даними з черговим клієнтом.

    Примітка. Дана програма (як і більшість реальних програм-серверів) самостійно своєї роботи не завершує, перебуваючи у нескінченному циклі обробки запитів клієнтів. Її виконання може бути перервано тільки ззовні шляхом надсилання їй сигналів (переривань) завершення. Правильно розроблена програма-сервер повинна обробляти такі сигнали, коректно завершуючи роботу (закриваючи, зокрема, за допомогою close socket з дескриптором s).

    5.2. Програма-клієнт

    Текст програми-клієнта на мові програмування СІ виглядає наступним чином

    1 # include

    2 # include

    3 # include

    4 # include

    5 # include

    6 # define SRV_HOST "delta"

    7 # define SRV_PORT 1234

    8 # define CLNT_PORT 1235

    9 # define BUF_SIZE 64

    10 # define TXT_ANSW "I am your clientn "

    11 main () (

    12 int s;

    13 int from_len;

    14 char buf [BUF_SIZE];

    15 struct hostent * hp;

    16 struct sockaddr_in clnt_sin, srv_sin;

    17 s = socket (AF_INET, SOCK_STREAM, 0);

    18 memset ((char *) & clnt_sin,'',

    sizeof (clnt_sin));

    19 clnt_sin.sin_family = AF_INET;

    20 clnt_sin.sin_addr.s_addr = INADDR_ANY;

    21 clnt_sin.sin_port = CLNT_PORT;

    22 bind (s, (struct sockaddr *) & clnt_sin,

    sizeof (clnt_sin));

    23 memset ((char *) & srv_sin,'',

    sizeof (srv_sin));

    24 hp = gethostbyname (SRV_HOST);

    25 srv_sin.sin_family = AF_INET;

    26 memcpy ((char

    *) & srv_sin.sin_addr, hp-> h_addr, hp-> h_length);

    27 srv_sin.sin_port = SRV_PORT;

    28 connect (s, & srv_sin, sizeof (srv_sin));

    29 from_len = recv (s, buf, BUF_SIZE, 0);

    30 write (1, buf, from_len);

    31 send (s, TXT_ANSW, sizeof (TXT_ANSW), 0);

    32 close (s);

    33 exit (0);

    34)

    У рядках 6 і 7 описуються константи SRV_HOST і SRV_PORT, що визначають ім'я віддаленого вузла, на якому функціонує програма-сервер, і номер порту, до якого прив'язаний socket сервера.

    Рядок 8 приписує цілочисельний константі 1235 символічне ім'я CLNT_PORT. Надалі ця константа буде використана в як номер порту клієнта.

    У рядках 17 ... 22 створюється прив'язаний до порту на локальному вузлі socket.

    У рядку 24 за допомогою бібліотечної функції gethostbyname транслюється символічне ім'я віддаленого вузла (в даному випадку "delta"), на якому має функціонувати сервер, на адресу цього вузла, розміщений у структурі типу hostent.

    В рядку 26 адреса віддаленого вузла копіюється з структури типу hostent у відповідне поле структури srv_sin, яка пізніше (у рядку 28) використовується в системному виклику connect для ідентифікації програми-сервера.

    У рядках 29 ... 31 здійснюється обмін даними з сервером і висновок питання, що надійшов від сервера, в стандартний вивід.

    Рядок 32 за допомогою системного виклику close закриває (видаляє) socket.

    Список літератури

    Для підготовки даної роботи були використані матеріали з сайту http://www.realcoding.net/

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status