UNIX: разработка сетевых приложений - Страница 44
Если мы запустим наш новый сервер, а затем запустим клиент на том же узле, то дважды соединившись с сервером, мы получим от клиента следующий вывод:
solaris % daytimetcpcli 127.0.0.1Thu Sep 11 12:44:00 2003solaris % daytimetcpcli 192.168.1.20Thu Sep 11 12:44:09 2003Сначала мы задаем IP-адрес сервера как адрес закольцовки на себя (loopback address) (127.0.0.1), а затем как его собственный IP-адрес (192.168.1.20). Вот соответствующий вывод сервера:
solaris # daytimetcpsrv1connection from 127.0.0.1, port 43388connection from 192.168.1.20, port 43389Обратите внимание на то, что происходит с IP-адресом клиента. Поскольку наш клиент времени и даты (см. листинг 1.1) не вызывает функцию
bindНаконец, заметьте, что приглашение интерпретатора команд изменилось на знак
#bindbindsolaris % daytimetcpsrv1bind error: Permission denied4.7. Функции fork и exec
Прежде чем рассматривать создание параллельного сервера (что мы сделаем в следующем разделе), необходимо описать функцию Unix
fork#include <unistd.h>pid_t fork(void);Возвращает: 0 в дочернем процессе, идентификатор дочернего процесса в родительском процессе, -1 в случае ошибкиЕсли вы никогда не встречались с этой функцией, трудным для понимания может оказаться то, что она вызывается один раз, а возвращает два значения. Одно значение эта функция возвращает в вызывающем процессе (который называется родительским процессом) — этим значением является идентификатор созданного процесса (который называется дочерним процессом). Второе значение (нуль) она возвращает в дочернем процессе. Следовательно, по возвращаемому значению можно определить, является ли данный процесс родительским или дочерним.
Причина того, что функция
forkgetppidforkВсе дескрипторы, открытые в родительском процессе перед вызовом функции
forkacceptforkСуществует два типичных случая применения функции
fork1. Процесс создает свои копии таким образом, что каждая из них может обрабатывать одно задание. Это типичная ситуация для сетевых серверов. Далее в тексте вы увидите множество подобных примеров.
2. Процесс хочет запустить другую программу. Поскольку единственный способ создать новый процесс — это вызвать функцию
forkforkexecforkЕдинственный способ запустить в Unix на выполнение какой-либо файл — вызвать функцию
execexecexecexecmainexecВ старых описаниях и книгах новая программа ошибочно называется «новым процессом». Это неверно, поскольку новый процесс не создается.
Различие между шестью функциями
exec■ выполняемый программный файл может быть задан или именем файла (filename), или полным именем (pathname);
■ аргументы новой программы либо перечисляются один за другим, либо на них имеется ссылка через массив указателей;
■ новой программе либо передается окружение вызывающего процесса, либо задается новое окружение.
#include <unistd.h>int execl(const char *pathname, const char *arg0, ... /* (char*)0 */ );int execv(const char *pathname, char *const argv[]);int execle(const char *pathname, const char *arg0 ... /* (char*)0, char *const envp[] */ );int execve(const char *pathname, char *const argv[], char *const envp[]);int execlp(const char *filename, const char *arg0, .... /* (char*)0 */ );