Библиотека сайта rus-linux.net
Возможности тулкита GTK+ и сопутствующих библиотек
Низкоуровневые функции для работы с сетью
Автор: A. Панин
Дата публикации: 11 июня 2015 г.
Современные приложения с графическим интерфейсом все чаще используют сетевые сервисы. Несмотря на то, что в приложениях с графическим интерфейсом на основе тулкита GTK+ могут вполне успешно применяться вызовы функций API Linux для работы с сетевыми сокетами, в рамках библиотеки GIO реализованы классы, позволяющие разрабатывать кроссплатформенные сетевые приложения. Бесспорным преимуществом упомянутых классов является тесная интеграция с механизмами, реализованными в рамках библиотеки GLib, среди которых следует особо выделить главный цикл обработки событий. Вообще говоря, набор классов, связанных с разработкой сетевых приложений в рамках библиотеки GIO достаточно обширен, поэтому в данной статье мы затронем лишь низкоуроневые функции для работы с сетью, реализованные в рамках класса GSocket а также механизм разрешения доменных имен, реализованный в рамках класса GResolver. Рассмотренных функций будет вполне достаточно для разработки как приведенных в статье простейших клиентских приложений, обменивающихся данными с сетевыми серверами по протоколам TCP и UDP, так и сложных приложений, использующих помимо упомянутых протоколов относительно новый протокол SCTP. Также в рамках библиотеки GLib реализованы более высокоуровневые классы для разработки сетевых приложений, о которых мы, возможно, поговорим в следующих статьях серии.
1. Класс сетевого сокета GSocket
Класс сетевого сокета GSocket
упрощает работу с сетевым сокетом в случае использования библиотеки GIO и реализует множество методов для управления состоянием этого сокета. Объект типа GSocket
может быть создан с помощью конструктора g_socket_new()
, а также с помощью специализированного конструктора g_socket_new_from_fd()
, причем в качестве аргумента последнего конструктора должен использоваться целочисленный дескриптор уже существующего сетевого сокета.
GSocket * g_socket_new(GSocketFamily family, GSocketType type, GSocketProtocol protocol, GError **error); GSocket * g_socket_new_from_fd(gint fd, GError **error);
В случае неудачной попытки создания объекта сетевого сокета оба конструктора возвращают значение NULL
и передают объект ошибки типа GError
с дополнительной информацией о возникшей ошибке. Если в случае второго конструктора единственным входным параметром является дескриптор действующего сокета, то в случае первого конструктора не все так очевидно, ведь требуется передать идентификаторы семейства протоколов, типа сокета и протокола. Допустимые идентификаторы с описаниями приведены в таблицах ниже.
Таблица 1 - Семейства протоколов сетевых сокетов
Семейство протоколов в рамках библиотеки GIO | Семейство протоколов в рамках системного API | Описание |
---|---|---|
G_SOCKET_FAMILY_INVALID |
- | Не установлено |
G_SOCKET_FAMILY_UNIX |
AF_UNIX |
Семейство протоколов домена UNIX |
G_SOCKET_FAMILY_IPV4 |
AF_INET |
Семейство протоколов IPv4 |
G_SOCKET_FAMILY_IPV6 |
AF_INET6 |
Семейство протоколов IPv6 |
Таблица 2 - Типы сетевых сокетов
Тип сетевого сокета в рамках библиотеки GIO | Тип сетевого сокета в рамках системного API | Описание |
---|---|---|
G_SOCKET_TYPE_INVALID |
- | Неизвестный или некорректный тип |
G_SOCKET_TYPE_STREAM |
SOCK_STREAM |
Сокет для надежной передачи байтового потока с установлением соединения (по протоколу TCP) |
G_SOCKET_TYPE_DATAGRAM |
SOCK_DGRAM |
Сокет для ненадежной передачи дейтаграмм без установления соединения (по протоколу UDP) |
G_SOCKET_TYPE_SEQPACKET |
SOC_SEQPACKET |
Сокет для надежной передачи дейтаграмм фиксированного максимального размера с установлением соединения (по протоколу SCTP) |
Таблица 3 - Протоколы сетевых сокетов
Протокол сетевого сокета в рамках библиотеки GIO | Описание |
---|---|
G_SOCKET_PROTOCOL_UNKNOWN |
Тип протокола неизвестен |
G_SOCKET_PROTOCOL_DEFAULT |
Стандартный протокол для заданного семейства протоколов/типа сетевого сокета |
G_SOCKET_PROTOCOL_TCP |
TCP/IP |
G_SOCKET_PROTOCOL_UDP |
UDP/IP |
G_SOCKET_PROTOCOL_SCTP |
SCTP/IP |
В большинстве случаев в качестве идентификатора протокола сетевого сокета может безопасно передаваться идентификатор стандартного протокола для заданного семейства/типа сетеврго сокета (G_SOCKET_PROTOCOL_DEFAULT
).
После создания объекта сетевого сокета активируется режим блокируемого ввода-вывода, который эмулируется на уровне библиотеки GIO, а не активиурется на уровне системы. Для нового сетевого сокета на уровне системы в любом случае активируется режим неблокируемого ввода-вывода. Такой режим работы сетевого сокета необходим для корректной интеграции в главный цикл обработки событий приложения, причем на уровне библиотеки GIO для изменения режима ввода-вывода может быть использован метод g_socket_set_blocking
()
, а для получения информация о режиме ввода-вывода объекта сетевого сокета - метод g_socket_get_blocking()
:
void g_socket_set_blocking(GSocket *socket, gboolean blocking); gboolean g_socket_get_blocking(GSocket *socket);
В случае использования режима неблокируемого ввода-вывода функции для работы с сетевыми сокетами будут немедленно возвращать либо результаты, либо объекты ошибок с идентификаторами G_IO_ERROR_WOULD_BLOCK
. В противном случае исполнение приложения (или программного потока, созданного в рамках приложения) будет блокироваться до момента возврата результата исполнения функции или объекта ошибки.
Для мультиплексирования ввода-вывода вместо специальных функций (select()
, poll()
, epoll()
) может использоваться как главный цикл обработки событий, так и цикл обработки событий из любого программного потока, созданного в рамках приложения. В случае необходимости мультиплексирования ввода-вывода может оказаться полезным как метод g_socket_create_source ()
, предназначенный для создания нового источника событий, который впоследствии может использоваться совместно с главным циклом обработки событий, так и методы g_socket_condition_check()
, g_socket_condition_wait()
и g_socket_condition_timed_wait()
, предназначенные для проверки состояния сетевого сокета и ожидания его перехода в заданное состояние (без указания и с указанием максимального периода ожидания соотвественно).
GSource * g_socket_create_source(GSocket *socket, GIOCondition condition, GCancellable *cancellable); GIOCondition g_socket_condition_check(GSocket *socket, GIOCondition condition); gboolean g_socket_condition_wait(GSocket *socket, GIOCondition condition, GCancellable *cancellable, GError **error); gboolean g_socket_condition_timed_wait(GSocket *socket, GIOCondition condition, gint64 timeout, GCancellable *cancellable, GError **error);
Два из трех приведенных выше методов мультиплексирования ввода-вывода принимают в качестве аргумента объект отмены операции для многопоточного приложения типа GCancellable
. Данный объект создается с помощью конструктора g_cancellable_new()
, а непосредственная отмена операции осуществляется с помощью его метода g_cancellable_cancel()
. Если вы не планируете прерывать операции установки соединений и обмена данными посредством сетевых сокетов, вы можете передавать значения NULL
вместо объектов отмены операций упомянутого типа.
GCancellable * g_cancellable_new(void); void g_cancellable_cancel(GCancellable *cancellable);
Во всех приведенных выше методах мультиплексирования ввода-вывода используются битовые маски условий операций ввода-вывода типа GIOCondition
. Допустимые значения условий операций ввода-вывода с соответствующими константами условий функции poll()
приведены в следующей таблице.
Таблица 4 - Условия операций ввода-вывода
Условие в рамках библиотеки GIO | Условие функции poll() | Описание |
---|---|---|
G_IO_IN |
POLLIN |
Данные доступны для чтения |
G_IO_OUT |
POLLOUT |
Данные могут быть записаны без блокировки |
G_IO_PRI |
POLLPRI |
Приоритетные данные доступны для чтения |
G_IO_ERR |
POLLERR |
Произошла ошибка |
G_IO_HUP |
POLLHUP |
Произошел обрыв соединения |
G_IO_NVAL |
POLLNVAL |
Некорректная операция, дескриптор сокета не был открыт. |
При задании битовой маски условий операций ввода-вывода не следует использовать условия G_IO_ERR
и G_IO_HUP
, так как их наступление будет отмечено в любом случае. Пример использования метода для создания источника событий g_socket_create_source()
с последующей обработкой событий в рамках основного цикла обработки событий приложения будет приведен позднее в рамках данной статьи. В случае истечения заданного периода ожидания будет возвращаться заданное условие операции ввода вывода, но после использования метода для обмена данными будет возвращаться ошибка с идентификатором G_IO_ERROR_TIMED_OUT
. Метод для проверки состояния сетевого сокета g_socket_condition_check()
никогда не блокируется. Методы ожидания перехода сетевого сокета в заданное состояние g_socket_condition_wait()
и g_socket_condition_timed_wait()
возвращают логическое значение TRUE
в случае успешного перехода сокета в заданное состояние и FALSE
в случае истечения установленного времени ожидания или принудительной отмены операции ожидания (с возвратом объектов ошибок с идентификаторами G_IO_ERROR_TIMED_OUT
и G_IO_ERROR_CANCELLED
соответственно).
Благодаря эмуляции режима блокируемого ввода-вывода на уровне библиотеки GIO становится возможной установка времени ожидания завершения операций с сетевыми сокетами. Время ожидания завершения операций для объекта сетевого сокета в секундах может быть установлено с помощью метода g_socket_set_timeout()
и получено с помощью метода g_socket_get_timeout()
.
void g_socket_set_timeout(GSocket *socket, guint timeout); guint g_socket_get_timeout(GSocket *socket);
В том случае, если для сетевого сокета активирован режим блокируемого ввода-вывода, все блокирующие операции будут завершаться по истечении заданного периода времени с возвратом объекта ошибки с идентификатором G_IO_ERROR_TIMED_OUT
. В случае использования режима неблокируемого ввода-вывода объекты ошибок с упомянутым идентификатором будут возвращаться по истечении заданного периода времени при работе с методом ожидания перехода сокета в заданное состояние (g_socket_condition_wait()
) и при использовании функций для обмена данными посредством сокета (причем перед возвратом объекта ошибки в случае обработки событий сокета в рамках основного цикла обработки событий приложения будут возвращаться идентификаторы заданных условий). Для того, чтобы отказаться от использования описанного механизма следует всего лишь передать значение 0
в качестве аргумента timeout
метода g_socket_set_timeout
()
.
Для соединения с удаленным узлом должен использоваться метод g_socket_connect()
. Данный метод может использоваться как при работе с протоколами, предусматривающими установку соединения (такими, как TCP), так и с протоколами, не предусматривающими установки соединения (такими, как UDP), причем в случае использования первого типа протоколов данный метод может вызываться лишь один раз, а в случае использования второго типа протоколов - множество раз для с целью задания нового адреса для отправки и приема дейтаграмм. При активации режима блокируемого ввода-вывода использование данного метода может приводить к блокировке, а в случае активации режима неблокируемого ввода-вывода может возвращаться объект ошибки с идентификатором G_IO_ERROR_PENDING
, причем в этом случае момент установки соединения может отслеживаться по наступлению состояния записи данных без блокировки (G_IO_OUT
), а корректность установки соединения может проверяться с помощью метода g_socket_check_connect_result()
.
gboolean g_socket_connect(GSocket *socket, GSocketAddress *address, GCancellable *cancellable, GError **error); gboolean g_socket_check_connect_result(GSocket *socket, GError **error);
Следует также обратить внимание на объект адреса сокета GSocketAddress
, используемый в качестве аргумента метода g_socket_connect()
. На самом деле следует использовать объект на основе класса GInetSocketAddress
при работе с сетевыми сокетами и на основе класса GUnixSocketAddress
при работе с сокетами домена UNIX. Объект на основе первого класса может создаваться как на основе объекта сетевого адреса на основе класса GSocketAddress
с указанием номера порта путем использования конструктора g_inet_socket_address_new()
, так и на основе строковой записи адреса узла и целочисленного номера порта путем использования конструктора g_inet_socket_address_new_from_string()
. Объект на основе второго класса создается с помощью конструктора g_unix_socket_address_new()
.
GSocketAddress * g_inet_socket_address_new(GInetAddress *address, guint16 port); GSocketAddress * g_inet_socket_address_new_from_string(const char *address, guint port); GSocketAddress * g_unix_socket_address_new(const gchar *path);
При разработке приложения, принимающего соединения, сетевой сокет должен получить адрес из заданного при его создании семейства адресов. Для этой цели может использоваться метод g_socket_bind()
. Данный метод в определенных ситуациях может использоваться и по отношению к сетевым сокетам, посредством которых будут инициироваться соединения с удаленными узлами, но в общем случае этого не требуется.
gboolean g_socket_bind(GSocket *socket, GSocketAddress *address, gboolean allow_reuse, GError **error);
Аргумент allow_reuse
позволяет произвести установку значения параметра SO_REUSEADDR
сетевого сокета сразу же после присваивания адреса этому сокету. В большинстве случаев следует использовать значение TRUE
при разработке приложений, принимающих соединения, и FALSE
при разработке приложений, инициирующих соединения. Возврат объекта ошибки с идентификатором G_IO_ERROR_ADDRESS_IN_USE
при использовании метода g_socket_bind()
после перезапуска приложения, принимающего соединения, является главным признаком некорректной установки значения данного аргумента.
Для перевода сетевого сокета в режим приема соединений после присваивания этому сокету адреса следует использовать метод g_socket_listen()
. Длина очереди запросов соединений может устанавливаться с помощью метода g_socket_set_listen_backlog()
и извлекаться с помощью метода g_socket_get_listen_backlog()
.
gboolean g_socket_listen(GSocket *socket, GError **error); void g_socket_set_listen_backlog(GSocket *socket, gint backlog); gint g_socket_get_listen_backlog(GSocket *socket);
Для непосредственного приема соединений после перевода сетевого сокета в соответствующий режим может использоваться метод g_socket_accept()
. В том случае, если в очереди запросов соединений имеются запросы, первый запрос будет извлечен из нее, а функция вернет новый объект сетевого сокета типа GSocket
. В том же случае, если очередь запросов соединений пуста, вызов рассматриваемого метода приведет к блокировке при активации режима блокируемого ввода-вывода или к возврату объекта ошибки с идентификатором G_IO_ERROR_WOULD_BLOCK
в противном случае. Поступление запросов соединений может отслеживаться по наступлению состояния доступности данных для чтения (G_IO_IN
).
GSocket * g_socket_accept(GSocket *socket, GCancellable *cancellable, GError **error);
Прием данных посредством сетевого сокета может осуществляться с помощью методов g_socket_receive()
, g_socket_receive_from()
, g_socket_receive_message()
и g_socket_receive_with_blocking()
.
gssize g_socket_receive(GSocket *socket, gchar *buffer, gsize size, GCancellable *cancellable, GError **error); gssize g_socket_receive_from(GSocket *socket, GSocketAddress **address, gchar *buffer, gsize size, GCancellable *cancellable, GError **error); gssize g_socket_receive_message(GSocket *socket, GSocketAddress **address, GInputVector *vectors, gint num_vectors, GSocketControlMessage ***messages, gint *num_messages, gint *flags, GCancellable *cancellable, GError **error); gssize g_socket_receive_with_blocking(GSocket *socket, gchar *buffer, gsize size, gboolean blocking, GCancellable *cancellable, GError **error);
Первый метод g_socket_receive()
является наиболее простым и предназначен для приема данных посредством соединенного сетевого сокета. С помощью аргумента buffer
передается указатель на область памяти, в которую будут скопированы принятые данные, а с помощью аргумента size
- размер этой области. При работе с протоколами, предусматривающими передачу дейтаграмм, с помощью рассматриваемого метода может быть принята либо одна дейтаграмма, либо не принято дейтаграмм вообще, причем в случае недостаточного размера фрагмента памяти принятая дейтаграмма будет урезана. При работе с протоколами, предусматривающими передачу потока данных, с помощью данного метода может быть принят любой объем данных, не превышающий переданный размер фрагмента памяти. Данный метод аналогичен системной функции recv
()
. При активации режима блокируемого ввода-вывода и отсутствии данных для приема вызов метода может повлечь за собой блокировку, а при активации режима неблокируемого ввода-вывода - возврат объекта ошибки с идентификатором G_IO_ERROR_WOULD_BLOCK
. Отслеживание появления данных для приема может осуществляться по наступлению соответствующего состояния (G_IO_IN
). Метод возвращает количество принятых байт, значенние 0
в случае закрытия соединения на на другой строне или значение -1
в случае ошибки. Второй метод g_socket_receive_from
()
предназначен для приема данных посредством несоединенного сетевого сокета. Он работает аналогично первому методу, но позволяет задать адрес узла для приема данных или принять данные с произвольного узла. По сути данный метод является аналогом системной функции recvfrom()
. Третий метод является самым мощным и чаще всего используется для работы с сокетами домена UNIX и Netlink-сокетами. Данный метод предполагает использование наборов векторов ввода типа GInputVector
(являющихся простыми буферами с указанной длиной) и передаваемых посредством ядра ОС управляющих сообщений типа GSocketControlMessage
(к примеру, наборов файловых дескрипторов или пользовательских прав). Кроме того, вы можете задействовать аргумент flags
для указания флагов, к примеру, с целью передачи внеполосных данных. Данный метод является упрощенным аналогом системной функции recvmsg()
. Последний метод полностью аналогичен первому, за исключением того, что вы можете активировать режим блокируемого или неблокируемого ввода-вывода для отдельной операции с помощью аргумента blocking
.
В случае резервирования динамического буфера для приема данных посредством сетевого сокета может оказаться полезным метод g_socket_get_available_bytes()
, позволяющий получить информацию об объеме буферизованных данных в очереди приема сетевого сокета, которые могут быть приняты без блокировки.
gssize g_socket_get_available_bytes(GSocket *socket);
Отправка данных по аналогии с приемом данных может осуществляться с помощью четырех методов, а именно: g_socket_send()
, g_socket_send_to()
, g_socket_send_message()
и g_socket_send_with_blocking()
.
gssize g_socket_send(GSocket *socket, const gchar *buffer, gsize size, GCancellable *cancellable, GError **error); gssize g_socket_send_to(GSocket *socket, GSocketAddress *address, const gchar *buffer, gsize size, GCancellable *cancellable, GError **error); gssize g_socket_send_message(GSocket *socket, GSocketAddress *address, GOutputVector *vectors, gint num_vectors, GSocketControlMessage **messages, gint num_messages, gint flags, GCancellable *cancellable, GError **error); gssize g_socket_send_with_blocking(GSocket *socket, const gchar *buffer, gsize size, gboolean blocking, GCancellable *cancellable, GError **error);
По аналогии с методами для приема данных с помощью аргумента buffer
передается указатель на область памяти с данными, которые необходимо передать посредством сетевого сокета, а с помощью аргумента size
- задается объем этих данных. Первый метод (g_socket_send
()
) используется главным образом при работе с протоколами, предусматривающими установку соединения, и аналогичен системной функции send()
. В случае активации режима блокируемого ввода-вывода и недостатка места в очереди отправки данный метод будет блокироваться до момента передачи данных из этой очереди в объеме, достаточном для копирования переданных данных в нее. При активации режима неблокируемого ввода-вывода в аналогичной ситуации будет возвращен объект ошибки с идентификатором G_IO_ERROR_WOULD_BLOCK
. Для отслеживания моментов освобождения места в очереди отправки сетевого сокета следует ожидать наступления соотествующего состояния (G_IO_OUT
), причем даже после его наступления в некоторых случаях вы можете столкнуться с ранее упомянутой ошибкой с идентификатором G_IO_ERROR_WOULD_BLOCK
. Метод возвращает количество отправленных байт или значение -1
в случае ошибки. Второй метод (g_socket_send_to
()
) очень похож на первый, но используется главным образом при работе с протоколами, не предусматривающими установки соединения, и аналогичен системной функции sendto()
. С помощью аргумента address
задается адрес целевого узла для отправки данных. Третий метод (g_socket_send_message
()
) является самым мощным методом для отправки данных посредством сетевого сокета и предусматривает возможность передачи данных, упакованных в векторы вывода типа GOutputVector
, передачи управляющих сообщений типа GSocketControlMessage
, а также установки флагов сообщений. Как и соответствующий метод приема данных, данный метод используется главным образом при работе с сокетами домена UNIX, Netlink-сокетами, а также в случае необходимости установки флагов. Данный метод является упрощенным вариантом системной функции sendmsg()
. Последний метод (g_socket_send_with_blocking
()
) полностью аналогичен первому методу за исключением того, что вы можете активировать режим блокируемого или неблокируемого ввода-вывода на уровне отдельной операции с помощью аргумента blocking
.
В некоторых случаях при разработке сетевых приложений приходится задавать параметры сокетов, причем в случае работы с системным API сокетов для этих целей используются функции setsockopt()
и getsockopt()
. Библиотека GIO, в свою очередь, предлагает разработчику методы g_socket_set_option()
и g_socket_get_option()
для установки и получения целочисленных значений произвольных параметров сокетов, а также множество специализированных методов для установки и получения значений наиболее востребованных нечисловых параметров.
gboolean g_socket_set_option(GSocket *socket, gint level, gint optname, gint value, GError **error); gboolean g_socket_get_option(GSocket *socket, gint level, gint optname, gint *value, GError **error);
С помощью аргумента level
задается "уровень API" (SOL_SOCKET
, IPPROTO_IP
, IPPROTO_ICMPV6
, IPPROTO_IPV6
, IPPROTO_TCP
), с помощью аргумента optname
- идентификатор параметра, а с помощью аргумента value
- целочисленное значение параметра. В том случае, если необходимо установить или получить значение параметра сокета, не являющееся целочисленным, следует использовать непосредственно функции setsockopt()
и getsockopt()
. Для получения доступа к объявлениям идентификаторов уровней API и параметров следует подключить либо заголовочный файл <gio/gnetworking.h>
, либо необходимые системные заголовочные файлы.
Управление механизмом проверки работоспособности соединения может осуществляться с помощью специализированного метода g_socket_set_keepalive()
, а проверка состояния этого механизма - с помощью метода g_socket_get_keepalive()
. Разумеется, данный механизм работоспособен исключительно в случае использования протокола, предусматривающего установку соединения, например, протокола TCP. Интервал проверок зависит от реализации сетевого стека и выбранного протокола и может изменяться сразу для всех сетевых сокетов в рамках системы.
void g_socket_set_keepalive(GSocket *socket, gboolean keepalive); gboolean g_socket_get_keepalive(GSocket *socket);
Время жизни отправленных посредством сокета сетевых пакетов пакетов может быть установлено с помощью метода g_socket_set_ttl()
и получено с помощью метода g_socket_get_ttl()
.
void g_socket_set_ttl(GSocket *socket, guint ttl); guint g_socket_get_ttl(GSocket *socket);
Возможность отправки многоадресных дейтаграмм может быть активирована с помощью метода g_socket_set_broadcast()
и проверена с помощью метода g_socket_get_broadcast()
.
void g_socket_set_broadcast(GSocket *socket, gboolean broadcast); gboolean g_socket_get_broadcast(GSocket *socket);
Существует и несколько методов, относящихся к режиму многоадресной передачи данных. Время жизни пакетов в случае многоадресной передачи, может быть задано с помощью метода g_socket_set_multicast_ttl()
и получено с помощью метода g_socket_get_multicast_ttl()
. Режим передачи копий пакетов на узел, с которого они были переданы, может быть изменен с помощью метода g_socket_set_multicast_loopback()
и получен с помощью метода g_socket_get_multicast_loopback()
.
void g_socket_set_multicast_ttl(GSocket *socket, guint ttl); guint g_socket_get_multicast_ttl(GSocket *socket); void g_socket_set_multicast_loopback(GSocket *socket, gboolean loopback); gboolean g_socket_get_multicast_loopback(GSocket *socket);
Для присоединения к группе многоадресной передачи и выхода из нее могут использоваться методы g_socket_join_multicast_group()
и g_socket_leave_multicast_group()
соответственно.
gboolean g_socket_join_multicast_group(GSocket *socket, GInetAddress *group, gboolean source_specific, const gchar *iface, GError **error); gboolean g_socket_leave_multicast_group(GSocket *socket, GInetAddress *group, gboolean source_specific, const gchar *iface, GError **error);
Очевидно, что с помощью аргумента iface
задается сетевой интерфейс, который будет использоваться для передачи пакетов, а с помощью аргумента source_specific
может активироваться механизм многоадресной передачи данных с заданным источником, описанный в стандарте RFC 4604.
Существуют и дополнительные методы, позволяющие получить параметры сетевого сокета. Метод g_socket_get_family()
позволяет получить идентификатор семейства протоколов, с которым работает сетевой сокет, метод g_socket_get_fd()
- дескриптор или хэндл сетевого сокета, метод g_socket_get_local_address()
- локальный адрес связанного сетевого сокета, метод g_socket_get_remote_address()
- удаленный адрес связанного сетевого сокета, метод g_socket_get_protocol()
- идентификатор протокола, который используется сетевым сокетом, метод g_socket_get_socket_type()
- идентификатор типа сетевого сокета, метод g_socket_speaks_ipv4()
- информацию о возможности работы с протоколом IPv4 при условии использования сетевого сокета.
GSocketFamily g_socket_get_family(GSocket *socket); int g_socket_get_fd(GSocket *socket); GSocketAddress * g_socket_get_local_address(GSocket *socket, GError **error); GSocketAddress * g_socket_get_remote_address(GSocket *socket, GError **error); GSocketProtocol g_socket_get_protocol(GSocket *socket); GSocketType g_socket_get_socket_type(GSocket *socket); gboolean g_socket_speaks_ipv4(GSocket *socket);
Так как класс сетевого сокета GSocket
является классом, унаследованным от класса GObject
, он использует счетчик ссылок, значение которого равно 1 при создании объекта. При достижении нулевого значения счетчика ссылок сетевой сокет будет автоматически закрыт, а объект сетевого сокета - уничтожен. Для установки и удаления ссылок на объект могут использоваться стандартные методы g_object_ref()
и g_object_unref()
. Кроме того, существует метод g_socket_close()
для явного закрытия сетевого сокета, метод g_socket_is_closed()
для проверки корректности его закрытия и метод g_socket_shutdown()
для частичного или полного прекращения полнодуплексной передачи данных посредством сетевого сокета.
gboolean g_socket_close(GSocket *socket, GError **error); gboolean g_socket_is_closed(GSocket *socket); gboolean g_socket_shutdown(GSocket *socket, gboolean shutdown_read, gboolean shutdown_write, GError **error);
В последнем методе аргумент shutdown_read
позволяет прекратить передачу данных от удаленных узлов, а аргумент shutdown_write
- передачу данных удаленным узлам.
Как вы могли заметить, названия методов очень похожи на названия системных функций API сокетов, следовательно, все описанные в различной литературе приемы сетевого программирования могут с успехом применяться и в случае разработки сетевых приложений на основе библиотек GLib/GIO.
Продолжение статьи : 2. Класс системы разрешения доменных имен GResolver.