Программирование POSIX сокет. Сукиязов С.А. - 8 стр.

UptoLike

Составители: 

Листинг 2 Использование функции connect ()
/***************************************************************/
/*** Фрагмент программы, демонстрирующий инициализацию ***/
/*** параметров и вызов функции connect(). ***/
/***************************************************************/
#define PORTJTIME 13
struct sockaddr_in dest;
char *host = "127.0.0.1";
int sd;
/**** Создание сокета ****/
...
bzero(&dest, sizeof(dest)); /* обнуляем структуру */
dest.sin_family = AF_INET; /* выбираем протокол */
dest.sin_port = htons(PORT_TIME); /* выбираем порт */
inet_aton(host, &dest.sin_addr); /* задаем адрес */
if ( connect(sd, &dest, sizeof(dest)) != 0 ) /* подключаемся! */
{
perror("socket connection");
abort();
}
Перед подключением к серверу выполняется ряд подготовительных действий. В первую очередь
создается структура sockaddr_in. Затем объявляется переменная, содержащая адрес, по которому будет
произведено обращение. После этого выполняются другие, не показанные здесь, операции, включая вы-
зов функции socket(). Функция bzero() заполняет структуру sockaddr_in нулями. Поле sin family устанав-
ливается равным AF_INET. Далее задаются номер порта и IP-адрес. Функции htons () и
inet_aton(), вы-
полняющие преобразования типов данных, рассматриваются в главе 2, "Основы TCP/IP".
Наконец, осуществляется подключение к серверу. Обратите внимание на необходимость провер-
ки значения, возвращаемого функцией connect(). Это один из многих приемов, позволяющих повысить
надежность сетевых приложений.
После установления соединения дескриптор сокета, sd, становится дескриптором ввода-вывода,
доступным обеим программам. Большинство серверов ориентировано на выполнение
единственной
транзакции, после чего разрывают соединение (например, сервер HTTP 1.0 отправляет запрашиваемый
файл и отключается). Взаимодействуя с такими серверами, программа должна посылать запрос, полу-
чать ответ и закрывать сокет.
Получение ответа от сервера
Итак, сокет открыт, и соединение установлено. Можно начинать разговор. Некоторые серверы
инициируют диалог подобно людям, разговаривающим по телефону. Они как бы говорят: "Алло!" При-
ветственное сообщение может включать имя сервера и определенные инструкции.
Когда сокет открыт, можно вызывать стандартные низкоуровневые функции ввода-вывода для
приема и передачи данных. Ниже приведено объявление
функции read():
#include <unistd.h>
ssize_t read(int fd, void *buf, size t count);
Эта функция должна быть вам знакома. Вы много раз применяли ее при работе с файлами, только
на этот раз необходимо указывать дескриптор не файла (fd), а сокета (sd) , Вот как обычно организуется
вызов функции функции read () :
...
int sd, bytes_read;
sd = socket(PF_INET, SOCK_STREAM, 0); /* создание сокета */
/**** Подключение к серверу ****/
bytes_read = read(sd, buffer, MAXBUF); /* чтение данных */
if ( bytes_read < 0 )
/* сообщить об ошибках; завершить работу */
Дескриптор сокета можно даже преобразовать в файловый дескриптор (FILE*), если требуется
работать с высокоуровневыми функциями ввода-вывода. Например, в следующем фрагменте программы
демонстрируется, как применить функцию fscanf() для чтения данных с сервера (строки, на которые
следует обратить внимание, выделены полужирным шрифтом):
char Name[NAME], Address[ADDRESS], Phone[PHONE];
FILE *sp;
Листинг 2 Использование функции connect ()
/***************************************************************/
/***    Фрагмент программы, демонстрирующий инициализацию    ***/
/***    параметров и вызов функции connect().                ***/
/***************************************************************/
#define PORTJTIME    13
struct sockaddr_in dest;
char *host = "127.0.0.1";
int sd;
/**** Создание сокета ****/
...
bzero(&dest, sizeof(dest));              /* обнуляем структуру */
dest.sin_family = AF_INET;                /* выбираем протокол */
dest.sin_port = htons(PORT_TIME);             /* выбираем порт */
inet_aton(host, &dest.sin_addr);               /* задаем адрес */
if ( connect(sd, &dest, sizeof(dest)) != 0 ) /* подключаемся! */
{
  perror("socket connection");
  abort();
}


      Перед подключением к серверу выполняется ряд подготовительных действий. В первую очередь
создается структура sockaddr_in. Затем объявляется переменная, содержащая адрес, по которому будет
произведено обращение. После этого выполняются другие, не показанные здесь, операции, включая вы-
зов функции socket(). Функция bzero() заполняет структуру sockaddr_in нулями. Поле sin family устанав-
ливается равным AF_INET. Далее задаются номер порта и IP-адрес. Функции htons () и inet_aton(), вы-
полняющие преобразования типов данных, рассматриваются в главе 2, "Основы TCP/IP".
      Наконец, осуществляется подключение к серверу. Обратите внимание на необходимость провер-
ки значения, возвращаемого функцией connect(). Это один из многих приемов, позволяющих повысить
надежность сетевых приложений.
       После установления соединения дескриптор сокета, sd, становится дескриптором ввода-вывода,
доступным обеим программам. Большинство серверов ориентировано на выполнение единственной
транзакции, после чего разрывают соединение (например, сервер HTTP 1.0 отправляет запрашиваемый
файл и отключается). Взаимодействуя с такими серверами, программа должна посылать запрос, полу-
чать ответ и закрывать сокет.

      Получение ответа от сервера
      Итак, сокет открыт, и соединение установлено. Можно начинать разговор. Некоторые серверы
инициируют диалог подобно людям, разговаривающим по телефону. Они как бы говорят: "Алло!" При-
ветственное сообщение может включать имя сервера и определенные инструкции.
     Когда сокет открыт, можно вызывать стандартные низкоуровневые функции ввода-вывода для
приема и передачи данных. Ниже приведено объявление функции read():
#include 
ssize_t read(int fd, void *buf, size t count);


      Эта функция должна быть вам знакома. Вы много раз применяли ее при работе с файлами, только
на этот раз необходимо указывать дескриптор не файла (fd), а сокета (sd) , Вот как обычно организуется
вызов функции функции read () :
...
int sd, bytes_read;
sd = socket(PF_INET, SOCK_STREAM, 0);    /* создание сокета */
/**** Подключение к серверу ****/
bytes_read = read(sd, buffer, MAXBUF);     /* чтение данных */
if ( bytes_read < 0 )
  /* сообщить об ошибках; завершить работу */


      Дескриптор сокета можно даже преобразовать в файловый дескриптор (FILE*), если требуется
работать с высокоуровневыми функциями ввода-вывода. Например, в следующем фрагменте программы
демонстрируется, как применить функцию fscanf() для чтения данных с сервера (строки, на которые
следует обратить внимание, выделены полужирным шрифтом):

char Name[NAME], Address[ADDRESS], Phone[PHONE];
FILE *sp;