UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Если мы запустим наш новый сервер, а затем запустим клиент на том же узле, то дважды соединившись с сервером, мы получим от клиента следующий вывод:
solaris % <b>daytimetcpcli 127.0.0.1</b>Thu Sep 11 12:44:00 2003solaris % <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 43388connection from 192.168.1.20, port 43389Обратите внимание на то, что происходит с IP-адресом клиента. Поскольку наш клиент времени и даты (см. листинг 1.1) не вызывает функцию
bindНаконец, заметьте, что приглашение интерпретатора команд изменилось на знак
#bindbindsolaris % <b>daytimetcpsrv1</b>bind error: Permission denied4.7. Функции fork и exec
Прежде чем рассматривать создание параллельного сервера (что мы сделаем в следующем разделе), необходимо описать функцию Unix
fork#include <unistd.h>pid_t fork(void);<i>Возвращает: 0 в дочернем процессе, идентификатор дочернего процесса в родительском процессе, -1 в случае ошибки</i>Если вы никогда не встречались с этой функцией, трудным для понимания может оказаться то, что она вызывается один раз, а возвращает два значения. Одно значение эта функция возвращает в вызывающем процессе (который называется родительским процессом) — этим значением является идентификатор созданного процесса (который называется дочерним процессом). Второе значение (нуль) она возвращает в дочернем процессе. Следовательно, по возвращаемому значению можно определить, является ли данный процесс родительским или дочерним.
Причина того, что функция
forkgetppidforkВсе дескрипторы, открытые в родительском процессе перед вызовом функции
forkacceptforkСуществует два типичных случая применения функции
fork1. Процесс создает свои копии таким образом, что каждая из них может обрабатывать одно задание. Это типичная ситуация для сетевых серверов. Далее в тексте вы увидите множество подобных примеров.
2. Процесс хочет запустить другую программу. Поскольку единственный способ создать новый процесс — это вызвать функцию
forkforkexecforkЕдинственный способ запустить в Unix на выполнение какой-либо файл — вызвать функцию
execexecexecexecmainexecВ старых описаниях и книгах новая программа ошибочно называется «новым процессом». Это неверно, поскольку новый процесс не создается.
Различие между шестью функциями
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 */ );
