Марк Митчелл - Программирование для Linux. Профессиональный подход
- Название:Программирование для Linux. Профессиональный подход
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2002
- Город:Москва
- ISBN:5-8459-0243-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.
Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.
Программирование для Linux. Профессиональный подход - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
#include
#include
/* Запись строки TEXT в сокет, заданный
дескриптором SOCKET_FD. */
void write_text(int socket_fd, const char* text) {
/* Сначала указывается число байтов в строке, включая
завершающий символ 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 (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-сервера, адрес которого указан в командной строке.
#include
#include
#include
#include
#include
#include
#include
/* Отображение содержимого 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]);
if (hostinfo == NULL)
return 1;
else
name sin_addr = *((struct in_addr*)hostinfo->h_addr);
/* Web-серверы используют порт 80. */
name.sin_port = htons(80);
/* Подключаемся к Web-серверу. */
if (connect(socket_fd, &name,
sizeof(struct sockaddr_in)) == -1) {
perror("connect");
return 1;
}
/* получаем содержимое начальной страницы сервера. */
get_home_page(socket_fd);
return 0;
}
Программа извлекает имя Web-сервера из командной строки (имя не является URL-адресом, т.е. в нем отсутствует префикс http://
). Далее вызывается функция gethostbyname()
, которая преобразует имя сервера в числовое представление. После этого программа подключает потоковый (TCP) сокет к порту 80 сервера. Web-серверы общаются по протоколу HTTP (Hypertext Transfer Protocol), поэтому программа посылает HTTP-команду GET, в ответ на которую сервер возвращает текст начальной страницы.
По существующему соглашению Web-серверы ожидают поступления запросов на порт 80. За большинством lntemet-сервисов закреплены стандартные номера портов. Например, защищенные Web-серверы работающие по протоколу SSL. прослушивают порт 443 а почтовые серверы (протокол SMTP) прослушивают порт 25
В Linux связи между именами протоколов/сервисов и номерами портов устанавливаются в файле /etc/services
. В первой колонке файла указано имя протокола или сервисе. Во второй колонке приведен номер порта и тип взаимодействия: tcp
— для сервисов ориентированных на соединения, и udp
— для дейтаграмм.
Интервал:
Закладка: