UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Если мы запустим наш новый сервер, а затем запустим клиент на том же узле, то дважды соединившись с сервером, мы получим от клиента следующий вывод:
solaris % <b>daytimetcpcli 127.0.0.1</b>
Thu Sep 11 12:44:00 2003
solaris % <b>daytimetcpcli 192.168.1.20</b>
Thu Sep 11 12:44:09 2003
Сначала мы задаем IP-адрес сервера как адрес закольцовки на себя (loopback address) (127.0.0.1), а затем как его собственный IP-адрес (192.168.1.20). Вот соответствующий вывод сервера:
solaris # <b>daytimetcpsrv1</b>
connection from 127.0.0.1, port 43388
connection from 192.168.1.20, port 43389
Обратите внимание на то, что происходит с IP-адресом клиента. Поскольку наш клиент времени и даты (см. листинг 1.1) не вызывает функцию
bind
Наконец, заметьте, что приглашение интерпретатора команд изменилось на знак
#
bind
bind
solaris % <b>daytimetcpsrv1</b>
bind error: Permission denied
4.7. Функции fork и exec
Прежде чем рассматривать создание параллельного сервера (что мы сделаем в следующем разделе), необходимо описать функцию Unix
fork
#include <unistd.h>
pid_t fork(void);
<i>Возвращает: 0 в дочернем процессе, идентификатор дочернего процесса в родительском процессе, -1 в случае ошибки</i>
Если вы никогда не встречались с этой функцией, трудным для понимания может оказаться то, что она вызывается один раз, а возвращает два значения. Одно значение эта функция возвращает в вызывающем процессе (который называется родительским процессом) — этим значением является идентификатор созданного процесса (который называется дочерним процессом). Второе значение (нуль) она возвращает в дочернем процессе. Следовательно, по возвращаемому значению можно определить, является ли данный процесс родительским или дочерним.
Причина того, что функция
fork
getppid
fork
Все дескрипторы, открытые в родительском процессе перед вызовом функции
fork
accept
fork
Существует два типичных случая применения функции
fork
1. Процесс создает свои копии таким образом, что каждая из них может обрабатывать одно задание. Это типичная ситуация для сетевых серверов. Далее в тексте вы увидите множество подобных примеров.
2. Процесс хочет запустить другую программу. Поскольку единственный способ создать новый процесс — это вызвать функцию
fork
fork
exec
fork
Единственный способ запустить в Unix на выполнение какой-либо файл — вызвать функцию
exec
exec
exec
exec
main
exec
В старых описаниях и книгах новая программа ошибочно называется «новым процессом». Это неверно, поскольку новый процесс не создается.
Различие между шестью функциями
exec
■ выполняемый программный файл может быть задан или именем файла (filename), или полным именем (pathname);
■ аргументы новой программы либо перечисляются один за другим, либо на них имеется ссылка через массив указателей;
■ новой программе либо передается окружение вызывающего процесса, либо задается новое окружение.
#include <unistd.h>
int execl(const char *<i>pathname</i>, const char *<i>arg0</i>, ... /* (char*)0 */ );
int execv(const char *<i>pathname</i>, char *const <i>argv</i>[]);
int execle(const char *<i>pathname</i>, const char *<i>arg0</i> ... /* (char*)0,
char *const <i>envp</i>[] */ );
int execve(const char *<i>pathname</i>, char *const <i>argv</i>[], char *const <i>envp</i>[]);
int execlp(const char *<i>filename</i>, const char *<i>arg0</i>, .... /* (char*)0 */ );