я узнаю о gsocket и хочу попытаться написать простую программу для обработки любого полученного пакета, но функция callback всегда вызывается, когда приходит только один пакет. Это мой простой код:
#include <glib.h>
#include <gio/gio.h>
#include <libsoup/soup.h>
#include <glib-object.h>
gboolean has_packet(GIOChannel *source, GIOCondition condition, gpointer data){
g_printf("has packet\n");
return TRUE;
}
int main(int argc, char **argv) {
g_type_init();
GInetAddress *iface_address = g_inet_address_new_from_string ("0.0.0.0");
GSocketAddress *bind_address = g_inet_socket_address_new (iface_address, 12345);
GSocket *sock;
GError *err = NULL;
sock = g_socket_new(G_SOCKET_FAMILY_IPV4,
G_SOCKET_TYPE_DATAGRAM,
G_SOCKET_PROTOCOL_UDP,
&err);
g_assert(err == NULL);
g_socket_bind(sock, bind_address, TRUE, &err);
g_assert(err == NULL);
//int fd = g_socket_get_fd(sock);
//GIOChannel* channel = g_io_channel_unix_new(fd);
//guint source = g_io_add_watch(channel, G_IO_IN,
// (GIOFunc) test, NULL);
//g_io_channel_unref(channel);
GSource *source = g_socket_create_source (sock, G_IO_IN,
NULL);
g_source_set_callback (source, (GSourceFunc)has_packet, NULL, NULL);
GMainLoop *loop = g_main_loop_new(NULL, FALSE);
g_source_attach(source ,g_main_loop_get_context(loop));
g_main_loop_run(loop);
g_main_loop_unref(loop);
}
Надеюсь, когда придет один пакет, только одна ссылка "имеет пакет" будет напечатана, но она будет работать вечно. Не могли бы вы помочь мне разобраться, куда я ошибаюсь.
UPDATE: мне нужно прочитать данные в сокете.
gboolean has_packet(GIOChannel *source, GIOCondition condition, gpointer data)
{
GSocket *sock = (GSocket *)data;
char buf[65536];
GSocketAddress *address = NULL;
gssize bytes;
GInputVector vector;
GSocketControlMessage **messages;
gint num_messages;
GError *error = NULL;
vector.buffer = buf;
vector.size = 65536;
bytes = g_socket_receive_message (sock,
&address,
&vector,
1,
&messages,
&num_messages,
NULL,
NULL,
&error);
g_printf("has packet\n");
g_printf("bytes = %zd\n", bytes);
g_printf("num_message = %d\n", num_messages);
return TRUE;
}
Вы должны return FALSE
(или return G_SOURCE_REMOVE
) из обратного вызова, если вы хотите, чтобы он вызывался один раз.
Кроме того, вы запускаете основной цикл с помощью g_main_loop_run()
и он будет работать вечно до g_main_loop_quit()
пор, пока не g_main_loop_quit()
. Таким образом, вы должны выйти из основного цикла в какой-то момент (предположительно, вы хотите, чтобы он вышел после g_main_loop_quit()
пакета, поэтому вы должны вызвать g_main_loop_quit()
в has_packet()
.