Изложение материала ориентировано на человека, который не только не сталкивался с сокетами раньше, но и вообще имеет смутные представления об устройстве и функционировании компьютерных сетей. Поэтому мы будем обзорно рассматривать и общетеоретические темы, которые необходимо знать, чтобы эффективно программировать сетевое взаимодействие, так что никакая предварительная подготовка в этих вопросах от читателя не требуется.
Глава разбита на две части. Первая посвящена стандартным сокетам, а вто рая — сокетам Windows. Термины достаточно условны и нуждаются в дополнительном пояснении. Строго говоря, стандартными называются сокеты Беркли (Berkley sockets), разработанные в университете Беркли для системы Unix. Как это ни парадоксально звучит, но сокеты Беркли появились до появления компьютерных сетей. Изначально они предназначались для взаимодействия между процессами в системе и только позже были приспособлены для TCP/IP. Работа с сокетами Беркли сделана максимально похожей на работу с файлами в Unix. В частности, для отправки и получения данных используются те же функции, что и для файлового ввода-вывода.
Сокеты в Windows не полностью совместимы с сокетами Беркли (например, для них предусмотрены специальные функции отправки и получения данных, переопределены некоторые типы данных и т.п.). Но возможности работы с сокетами в Windows можно разделить на две части: то, что укладывается в идеологию сокетов Беркли, хотя и реализовано несколько иначе, и то, что является специфичным для Windows. Ту часть реализации сокетов Windows, которая по функциональности соответствует сокетам Беркли, мы будем называть стандартными сокетами, а сокетами Windows (Windows sockets) — специфичные для Windows расширения.
Ориентироваться мы будем только на два протокола передачи данных — TCP и UDP. Хотя библиотека сокетов поддерживает и другие протоколы, но эти два, во-первых, применяются наиболее часто, а во-вторых, именно на них во многом ориентированы стандартные сокеты. Поэтому здесь мы не будем касаться особенностей работы функций библиотеки сокетов, которые проявляются только для протоколов, отличных от TCP и UDP. Объем информации, с которой придется познакомиться, и без того большой, а с другими протоколами легче ознакомиться потом, изучив TCP и UDP.
Сначала рассмотрим классические методы работы с сокетами, которые не учитывают ни существования окон и оконных сообщений, ни возможности распараллеливания работы программы на несколько нитей. Это. впрочем, не означает, что программа, использующая эти методы, должна быть безоконной и однонитевой, оконные и многонитевые программы есть среди примеров этого раздела. Просто приспосабливать стандартные сокеты к окнам и распараллеливанию приходится вручную, а не за счет средств самой библиотеки. Тем не менее из-за своей простоты стандартные сокеты нередко оказываются более удобными, чем сокеты Windows, даже в оконных приложениях.
2.1.1 Соглашения об именах
Первые библиотеки сокетов писались на языке С. В этом языке идентификаторы чувствительны к регистру символов, т.е., например, SOCKET
, Socket
и socket
— разные идентификаторы. Исторически сложилось, что имена встроенных в C типов данных пишутся в нижнем регистре, имена определенных в программе типов, макроопределений и констант — в верхнем, а имена функций — в смешанном (прописные буквы выделяют начала слов, например, GetWindowText
). Разработчики библиотеки сокетов несколько отошли от этих правил: имена всех стандартных сокетных функций пишутся в нижнем регистре. И хотя мы и программируем на Паскале, нечувствительном к регистру символов, все же будем придерживаться этой традиции, пусть это не удобно, зато не будет расхождений с другими источниками.
Чувствительность С к регистру символов создаст некоторые проблемы при переноce библиотек, написанных на этом языке, в Delphi. Это связано с тем, что разные объекты могут иметь имена, различающиеся только регистром символов, в частности, есть тип SOCKET
и функция socket
. Сохранить эти имена в Delphi невозможно. Чтобы избежать этой проблемы, разработчики Delphi при переносе библиотек к имени типа добавляют букву " Т
", причем независимо от того, существуют ли у этого типа одноименные функции или нет. Так, типу SOCKET
из С в Delphi соответствует TSocket
. Имена функций остаются без изменений.
Ранее был упомянут термин "макроопределение". Он может быть непонятен тем, кто не работал с языками С и C++, потому что в Delphi макроопределения отсутствуют. Нормальная последовательность трансляции программы в Delphi следующая: сначала компилятор создает объектный код, в котором вместо реальных адресов функций, переменных и т.п. стоят ссылки на них (на этапе компиляции эти адреса еще не известны). Затем компоновщик размещает объекты в памяти и заменяет ссылки реальными адресами. Так получается готовая к исполнению программа. В С/C++ трансляция включает в себя еще один этап: перед компиляцией текст программы модифицируется препроцессором, и компилятор получает уже несколько видоизмененный текст. Макроопределения, или просто макросы, — это директивы препроцессору, предписывающие ему, как именно нужно менять текст программы. Макрос задаст подмену: везде, где в программе встречается имя макроса, препроцессор изменяет его на тот текст, который задан при определении этого макроса. Определяются макросы с помощью директивы препроцессору #define
.
Читать дальше
Конец ознакомительного отрывка
Купить книгу