Чтение онлайн

ЖАНРЫ

Программирование для Linux. Профессиональный подход

Самьюэл Алекс

Шрифт:

завершающий символ NULL. */

 int length = strlen(text) + 1;

 write(socket_fd, &length, sizeof(length));

 /* Запись строки. */

 write(socket_fd, text, length);

}

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

 const char* const socket_name = argv[1];

 const char* const message = argv[2];

 int socket_fd;

 struct sockaddr_un name;

 /*
Создание сокета. */

 socket_fd = socket(PF_LOCAL, SOCK_STREAM. 0);

 /* Сохранение имени сервера в адресной структуре. */

 name.sun_family = AF_LOCAL;

 strcpy(name.sun_path, socket_name);

 /* Подключение к серверному сокету. */

 connect(socket_fd, &name, SUN_LEN(&name));

 /* передача сообщения, заданного в командной строке. */

 write_text(socket_fd, message);

 close(socket_fd);

 return 0;

}

Прежде чем отравить текст сообщения, клиент записывает в сокет число (хранится в переменной

length
), определяющее длину сообщения в байтах. На противоположной стороне сервер выясняет длину сообщения и выделяет для него буфер соответствующего размера, после чего читает само сообщение.

Чтобы проверить этот пример, запустите в одном терминальном окне серверную программу, указав путь к сокету, например:

% ./socket-server /tmp/socket

В другом окне запустите несколько раз клиентскую программу, задав тот же путь к сокету плюс требуемое сообщение:

% ./socket-client /tmp/socket "Hello, world."

% ./socket-client /tmp/socket "This is a test."

Сервер получит и отобразит эти сообщения. Чтобы закрыть сервер, пошлите ему сообщение "quit":

% ./socket-client /tmp/socket "quit"

5.5.6. Internet-сокеты

UNIX-сокеты используются для организации взаимодействия двух процессов, выполняющихся на одном компьютере. С другой стороны. Internet-сокеты позволяют соединять между собой процессы, работающие на разных компьютерах.

Пространству имен Internet соответствует константа

PF_INET
. Internet-сокеты чаще всего работают по протоколам TCP/IP. Протокол IP (Internet Protocol) отвечает за низкоуровневую доставку сообщений, осуществляя при необходимости их разбивку на пакеты и последующую компоновку. Доставка пакетов не гарантируется, поэтому они могут исчезать или приходить в неправильном порядке. Каждый компьютер в сети имеет свой IP-адрес. Протокол TCP (Transmission Control Protocol) функционирует поверх протокола IP и обеспечивает надежную доставку сообщений, ориентированную на установление соединений.

DNS-имена

Легче запоминать имена а не числа, поэтому служба DNS (Domain Name Service) закрепляет за IP-адресами доменные имена вида

www.codesourcery.com
. Служба DNS организована в виде всемирной иерархии серверов имен. Чтобы использовать доменные имена в программах, нет необходимости разбираться в протоколах DNS

Адрес Internet-сокета состоит из двух частей: адреса компьютера и номера порта. Эта информация хранится в структуре типа

sockaddr_in
. В поле
sin_family
необходимо записать константу
AF_INET
, указывающую на то, что адрес принадлежит пространству имен Internet.
В поле
sin_addr
хранится IP-адрес компьютера в виде 32-разрядного целого числа. Благодаря номерам портов можно различать сокеты, создаваемые на одном компьютере. В разных системах многобайтовые значения могут храниться с разным порядком следования байтов, поэтому с помощью функции
htons
необходимо преобразовать номер порта в число с сетевым порядком следования байтов.

Функция

gethostbyname
преобразует адрес компьютера из текстового представления — стандартного точечного (например, 10.10.10.1) или доменного (например,
www.codesourcery.com
) — во внутреннее 32-разрядное. Функция возвращает указатель на структуру типа
hostent
. IP-адрес находится в ее поле
h_addr
.

Программа, представленная в листинге 5.12, иллюстрирует работу с Internet-сокетами. Программа запрашивает начальную страницу у Web-сервера, адрес которого указан в командной строке.

Листинг 5.12. (socket-inet.c) Чтение страницы с Web-сервера

#include <stdlib.h>

#include <stdio.h>

#include <netinet/in.h>

#include <netdb.h>

#include <sys/socket.h>

#include <unistd.h>

#include <string.h>

/* Отображение содержимого Web-страницы, полученной из

серверного сокета. */

void get_home_page(int socket_fd) {

 char buffer[10000];

 ssize_t number_characters_read;

 /* Отправка HTTP-команды GET с запросом начальной страницы. */

 sprintf(buffer, "GET /\n");

 write(socket_fd, buffer, strlen(buffer));

 /* Чтение данных из сокета. Функция read может вернуть

не все данные сразу, поэтому продолжаем чтение, пока

не будут получены все данные. */

 while (1) {

number_characters_read = read(socket_fd, buffer, 10000);

if (number_characters_read == 0)

return;

/* Запись данных в стандартный выходной поток. */

fwrite(buffer, sizeof(char), number_characters_read, stdout);

 }

}

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

 int socket_fd;

 struct sockaddr_in name;

 struct hostent* hostinfo;

 /* Создание сокета. */

 socket_fd = socket(PF_INET, SOCK_STREAM, 0);

 /* Запись имени сервера в адресную структуру. */

 name.sin_family = AF_INET;

 /* Преобразование адреса из текстового представления во

внутреннюю форму. */

 hostinfo = gethostbyname(argv[1]);

Поделиться с друзьями: