Brian «Beej Jorgensen» Hall
beej@beej.us
Version 3.0.14
September 8, 2009
Copyright © 2009 Brian «Beej Jorgensen» Hall
Оригинал материала: http://beej.us/guide/bgnet/

1. Введение
1.1 Аудитория
1.2 Платформа и компилятор
1.3 Официальная страница и книги
1.4 Программистам Solaris и SunOS
1.5 Программистам Windows
1.6 E-Mail политика
1.7 Зеркалирование
1.8 Copyright и распространение

2. Что такое сокет?
2.1 Два типа Интернет-Сокетов
2.2 Теория сетей и низкие уровни

3. IP-адреса, структуры, и передача данных
3.1 IP-адреса, версии 4 и 6
3.2 Порядок следования байт
3.3 Структуры
3.4 IP-адреса, часть два

4. Переход от IPv4 к IPv6

5. Системные вызовы
5.1 getaddrinfo() — готовимся к запуску!
5.2 socket() — создаём дескриптор файла!
5.3 bind() — на каком я порту?
5.4 connect() — Эй, ты!
5.5 listen() — Кто-нибуть может мне позвонить?
5.6 accept() — спасибо за звонок на порт 3490.
5.7 send() и recv() — поговори со мной, детка!
5.8 sendto() и recvfrom() Поговрии со мной дейтаграммами!
5.9 close() и shutdown() — Уйди с глаз моих!
5.10 getpeername() — ты кто такой?
5.11 gethostname() — а я кто такой?

6. Взаимодействие Клиент-Сервер
6.1 Простой TCP-сервер
6.2 Простой TCP-клиент
6.3 UDP-сокеты

7. Чуть более продвинутая техника
7.1 Блокирование
7.2 select() — мультиплексирование синхронного I/O
7.3 Обработка частичного send()
7.4 Сериализация — как упаковывать данные
7.5 Сын инкапсуляции данных
7.6 Бродкаст пакеты — Hello, World!

8. Общие вопросы

Введение

Эй! Программирование сокетов тебя достало? Оно слишком заковыристо, чтобы изучить его по манам? Вы хотите писать сетевые программы, но у вас нет времени, чтобы разбираться в дебрях документации, чтобы всего лишь узнать, что перед connect() нужно вызывать bind() и т.д. и т.п.?

Знаете что? Я уже проделал эту грязную работу и горю желанием поделиться со всеми полученными знаниями! Вы сюда удачно зашли! Этот документ даст среднему программисту на C достаточно знаний, чтобы начать писать сетевые программы на C.

И ещё: я наконец нашел время и дополнил гайд информацией о программировании IPv6! Наслаждайтесь!

Аудитория

Этот документ написан в качестве учебника, а не справочного материала. Наверно, лучше всего он будет восприниматься теми, кто только начинает изучать программирование сокетов и ищет точку опоры. Это не полное глобальное руководство по программированию сокетов.
Надеюсь, однако, его будет достаточно, чтобы понять суть и смысл сокетов… 🙂

Платформа и компилятор

Код, приведённый в этом документе, был скомпилирован на компьютере под управлеием GNU/Linux компилятором GNU GCC. Однако, он будет работать и на любой другой платформе, использующей gcc. Естественно, это не касается windows — смотрите раздел Программистам Windows.

Официальный сайт и книги

Официальное и изначальное местонахождение этого документа — http://beej.us/guide/bgnet/. Там вы также найдете примеры кода и переводы руководства на различные языки.

Чтобы купить красиво переплетенные копии этого документа (некоторые называют их «книги»), посетите http://beej.us/guide/url/bgbuy. Я ценю заказы своих книг, поскольку они помогают поддерживать мой документо-писательский образ жизни!

Программистам Solaris и SunOS

При компиляции под Solaris/SunOS вам нужно указать компилятору дополнительные библиотеки для линковки. Для этого просто добавьте в строку компиляции: «-lnsl -lsocket -lresolv» , как-то так:

$ cc o server server.c lnsl lsocket lresolv

Если всё ещё возникают ошибки, добавьте ещё и «-lxnet». Я не знаю, что это такое, но у некоторых людей это решало проблему.

Другое узкое место — вызов setsockopt(). Прототип отличается от такогого в Linux, так что вместо

int yes=1;

используйте:

char yes=‘1’;

Так как у меня нет соляриса, я не тестировал ничего из этого. Всё это мне пришло в отзывах на e-mail.

Программистам Windows

Исторически этот гайд не рассчитан на windows. Просто потому, что windows я не люблю. Но стоит быть действительно честным и признать, что у windows есть огромная база программ и пользователей, и в сущности это прекрасная ОС.

Я всё ещё надеюсь, что вы попробуете Linux, BSD или любой другой Unix.
Но людям нравится то, что им нравится, и ребята под windows имеют право на свою долю информации. Этот документ полезен и им тоже, с небольшими изменениями в коде.

Во-первых, вы можете поставить такую штуку, как Cygwin. Это коллекция инструментов Unix под Windows. Насколько я понимаю, это позволит оставить код без изменений.

Но некоторые из вас, возможно, захотят писать код под чистый windows. Это очень плохо, и вы должны немедленно поставить Unix!
Нет-нет, шучу. Нужно быть windows-терпеливым ближайшие дни…

Во-первых, вы должны игнорировать почти все хэдер-файлы, которые я использую. Всё, что вам нужно включать, это:

#include <winsock.h>

Стоп! Ещё вы должны вызывать WSAStartup() перед всем остальным кодом, относящимся к сокетам. Выглядит это примерно так:

#include <winsock.h>

{
WSADATA wsaData;   // if this doesn’t work
//WSAData wsaData; // then try this instead

// MAKEWORD(1,1) for Winsock 1.1, MAKEWORD(2,0) for Winsock 2.0:

if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
fprintf(stderr, «WSAStartup failed.n»);
exit(1);
}

Также вам нужно прилинковать к проекту библиотеки: обычно это wsock32.lib или winsock32.lib или ws2_32.lib для winsock 2.0. В VC++ это может быть сделано через меню Проект, в меню Настройки… Выберите вкладку компилятор->линковка или что-то вроде того, и добавьте «wsock32.lib» (или какой-то другой похожый .lib).

Ну, я слышал, что это примерно так делается.

В конце работы с сокетами вы должны вызывать WSACleanup().

Если вы сделаете всё это, остальные примеры из этого учебника должны, по идее, работать, хоть и с некоторыми исключениями.
Во-первых, вместо close() вам нужно использовать closesocket(). select() работает только с дескриптором сокета, с дескриптором файла, как в unix, не работает.

Существует так же класс для работы с сокетами, CSocket, можете поискать его в учебниках.

Чтобы получить больше информации о Winsock, читайте Winsock FAQ.

Наконец, насколько я знаю, в windows, к сожалению, нет системы fork(), использующейся в некоторых примерах. Может быть, вы сможете прилинковать для форка библиотеку POSIX, или использовать вместо него CreateProcess(). Форк не принимает аргументов, а CreateProcess принимает миллиарды. Если вам не хочется в них разбираться, используйте CreateThread, это немного проще… К сожалению, дискуссия о многопоточности выходит за рамки этого документа.

1.6 E-Mail политика

Обычно я доступен по электронной почте, если вам нужна помощь или есть вопросы, так чир не стесняйтесь писать, но я не могу гарантировать свой ответ. Я веду довольно занятой жизни и Есть моменты, когда я просто не могу ответить на ваш вопрос. Когда так случается, я обычно просто удаляю сообщение. Ничего личного, у меня просто никогда не будет времени, чтобы дать подробный ответ, которого вы требуете.

Как правило, чем более объемный вопрос, тем менее вероятно, что я отвечу. Если вы можете сузить свой вопрос, прежде чем отправить его мне, и не забудьте включить любую соответствующую информацию (например, платформу, компилятор, сообщения об ошибках, которые вы получаете и все остальное, что, как вам кажется, может мне помочь в устранении неполадок), вы имеете гораздо больше шансов получить ответ.

Если вы не получите ответа, подумайте над ним еще некоторое время, попробуйте найти ответ, и если он по-прежнему неуловимым, то напишите мне снова с дополнительной информацией, которую Вы нашли и, надеюсь, этого мне будет достаточно для помощи вам.

Теперь, когда я загрузил вас мыслями о том, писать мне или не писать, я просто хочу, чтобы вы знали, что я в полной мере оценил все похвалы руководства, которые получил за эти годы. Знание, что книга используется для создания полезных и хороших вещей — реальная поднимает боевой дух, и радует! 🙂 Спасибо!

1.7 Зеркалирование

Зеркалирование этого материала более чем приветствуется, будь то государственные или частные сайты. Если вы опубликовали зеркало и хотите, чтобы я разместил ссылку на него на главной странице, напишите мне на beej@beej.us.

Авторские права и распространение

Руководство Beej по сетевому программированию © 2009 Brian «Beej Jorgensen» Hall.

За некоторыми исключениями исходного кода и переводов, ниже, эта работа под лицензией Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 License. Чтобы просмотреть копию данной лицензии, посетите http://creativecommons.org/licenses/by-nc-nd/3.0/ или отправьте письмо в Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.

Одним из конкретных исключений «No Derivative Works» части лицензии является следующее: это руководство может быть свободно переведено на любой язык при условии, что перевод является точным, и руководство перепечатано в полном объеме. Такие же ограничения лицензии относятся как переводу, так и к исходному руководству. Перевод может также включать имя и контактную информацию переводчиков.

Исходный код, представленный в данном документе, настоящим объявляется общественным достоянием, и полностью свободен от каких-либо лицензионных ограничений.

Педагогам свободно предлагается рекомендовать или предоставить копии этого руководства своим студентам.

Свяжитесь с beej@beej.us для получения дополнительной информации.