UNIX: разработка сетевых приложений - Страница 50
5.6. Нормальный запуск
Наш небольшой пример использования TCP (около 150 строк кода для двух функций
mainstr_echostr_clireadlinewritenСначала мы запускаем сервер в фоновом режиме на узле
linuxlinux % tcpserv01 &[1] 17870Когда сервер запускается, он вызывает функции
socketbindlistenacceptacceptnetstatlinux % netstat -aActive Internet connections (servers and established)Proto Recv-Q Send-Q Local Address Foreign Address Statetcp 0 0 *:9877 *:* LISTENЗдесь мы показываем только первую строку вывода и интересующую нас строку. Эта команда показывает состояние всех сокетов в системе, поэтому вывод может быть большим. Для просмотра прослушиваемых сокетов следует указать параметр
-aРезультат совпадает с нашими ожиданиями. Сокет находится в состоянии LISTEN, локальный IP-адрес задан с помощью символа подстановки (то есть является универсальным) и указан локальный порт 9877. Функция
netstatINADDR_ANYЗатем на том же узле мы запускаем клиент, задав IP-адрес сервера 127.0.0.1. Мы могли бы задать здесь и нормальный адрес сервера (его IP-адрес в сети).
linux % tcpcli01 127.0.0.1Клиент вызывает функции
socketconnectaccept1. Клиент вызывает функцию
str_clifgets2. Когда функция
acceptforkstr_echoread3. Родительский процесс сервера снова вызывает функцию
acceptУ нас имеется три процесса, и все они находятся в состоянии ожидания (блокированы): клиент, родительский процесс сервера и дочерний процесс сервера.
Мы специально поставили первым пунктом (после завершения трехэтапного рукопожатия) вызов функции str_cli, происходящий на стороне клиента, а затем уже перечислили действия на стороне сервера. Причину объясняет рис. 2.5: функция connect возвращает управление, когда клиент получает второй сегмент рукопожатия. Однако функция accept не возвращает управление до тех пор, пока сервер не получит третий сегмент рукопожатия, то есть пока не пройдет половина периода RTT после завершения функции connect.
Мы намеренно запускаем и клиент, и сервер на одном узле — так проще всего экспериментировать с клиент-серверными приложениями. Поскольку клиент и сервер запущены на одном узле, функция
netstatl
inux % netstat -aProto Recv-Q Send-Q Local Address Foreign Address Statetcp 0 0 localhost:9877 localhost:42758 ESTABLISHEDtcp 0 0 localhost:42758 localhost:42758 ESTABLISHEDtcp 0 0 *:9877 *:* LISTENПервая из строк состояния
ESTABLISHEDESTABLISHEDДля проверки состояний процессов и отношений между ними можно также использовать команду
pslinux % ps -t pts/6 -o pid,ppid,tty,stat,args,wchanPID PPID TT STAT COMMAND WCHAN22038 22036 pts/6 S -bash wait417870 22038 pts/6 S ./tcpserv01 wait_for_connect19315 17870 pts/6 S ./tcpserv01 tcp_data_wait19314 22038 pts/6 S ./tcpcli01 127.0.0.1 read_chanМы вызвали
pspts/6PIDPPIDtcpserv01tcpserv01bashКолонка
STATSWCHANwait_for_connectacceptconnecttcp_data_waitread_chanWCHAN