dementiy 23.01.2010 19:45
Coding — Создание сокетов в Linux
Wikipedia гласит, что сокет - «название программного интерфейса для обеспечения обмена данными между процессами. Процессы при таком обмене могут исполняться как на одной ЭВМ, так и на различных ЭВМ, связанных между собой сетью. Сокет — абстрактный объект, представляющий конечную точку соединения.».Рассмотрим простой пример применения сокетов:
client.c:
Итак рассмотрим, что представляет из себя структура struct sockaddr_in. Данная структура определена следующим образом:
/usr/include/netinet/in.h:
/usr/include/bits/sockaddr.h:
1 |
...
|
Полю sin_family присваивается значение AF_INET, что соответствует протоколу TCP/IP версии 4 (AF_INET6 – версия 6), sin_port и sin_addr номер порта и адрес сервера соответственно. Данные этой структуры используются при установлении соединения. После заполнения структуры происходит вызов функции socket():
/usr/include/sys/socket.h:
Итак, как видно из комментария, данная функция создает новый сокет и при успешном выполнении возвращает дескриптор на созданный сокет, при возникновении ошибки возвращает значение меньше 0 (аналогично работе функции open()). Теперь рассмотрим, что происходит после ее вызова в ядре.
Запускаем клиентскую часть, как и ранее (Механизмы создания процессов в Linux) выполняя трассировку программы:
Примечание: strace раскрывает «непонятные» цифры 2, 1, 0.
Как видно происходит системный вызов sys_socketcall:
net/socket.c:
Данная функция представляет собой в некотором роде «свитч» для системных вызовов. В переменной call устанавливается номер требуемой функции. Данные номера определены в файле include/linux/net.h:
Как видно на данный момент (версия ядра 2.6.28) их всего 18, что соответствует количеству операторов case в sys_socketcall. В нашем случае в переменной call находится значение равное 1, что соответствует вызову SYS_SOCKET, то есть созданию сокета (при установлении соединения, как нетрудно догадаться, это значение будет соответствовать 3 — SYS_CONNECT).
Как выяснилось происходит вызов системного вызова sys_socket() с передачей трех аргументов, которые мы задали в функции soket() (о параметрах можно почитать на страницах справочного руководства man 2 socket или на сайте opennet). Функция sys_socket() определена в файле net/socket.c:
Значение retval является тем самым дескриптором, который возвращает пользовательская функция soket(). Структура struct socket, описывающая сокет, определена следующим образом:
include/linux/net.h:
Итак в функции sys_soсket() происходит вызов sock_create(), в которой заполняется структура struct soсket и выделяется память под сокет (sock_alloc). Функция sock_map_fd() связывает созданный сокет с дескриптором (тот, который мы используем в пользовательском приложении).
Таким образом выстраивается следующая (обобщенная) схема создания сокета:
soket() ? sys_socketcall() ? sys_socket() ? sock_create() ? sock_alloc()
P.S. Во-первых может возникнуть вопрос зачем приводится код клиента и сервера, когда для данной статьи можно было
обойтись всего лишь конструкцией вида:
1 |
|
Да можно было поступить и так, но мне показалось, что если статья не будет интересной (надеюсь это не так), то вы сможете
поиграться хотя бы с программой.
Во-вторых. Рассмотрено конечно же не все и не так подробно, как хотелось бы, но надеюсь, что для дальнейшего самостоятельного изучения этого достаточно.
И последнее, вот pdf (и тут).
Желаю успехов!
В server.c пришлось дописать объявление функции char *inet_ntoa(struct in_addr in). Без этого компилятор упорно думал что функция возвращает int, и при установке соединения, сервер падал. В принципе это логично, т.к. в С, если не описана функция, то считается что она возвращает int, но вроде подключены нужные заголовки, так что хз))
P.S. Спасибо за статьи, очень интересно, с нетерпением жду следующей))
P.P.S. Какие бумажные книжки стоит почитать по теме программирования под Linux? (Что-то по теме этой статьи)
P.S. Спасибо за статьи, очень интересно, с нетерпением жду следующей))
P.P.S. Какие бумажные книжки стоит почитать по теме программирования под Linux? (Что-то по теме этой статьи)
Еще статьи обязательно будут. На счет книг. Если интересует разработка сетевых приложений, то есть книга Стивенса, которая так и называется "Unix. Разработка сетевых приложений". Если что-то по программированию в Linux вообще, то Джонсон и Троан "Разработка приложений в среде Linux". А если проявляете интерес к ядру, то на моей памяти есть всего три книги, но покупать ни одну из них не советую, так как не очень хороший перевод.
P.S. За статью респект!