Получение мусора от GSocket
Я использую следующие функции для создания и открытия GSocket, а затем прослушиваю UDP-сообщения для отображения в поле GTK_ENTRY. Вызывается функция open_listen_socket, а затем по тайм-ауту у меня есть функция, вызывающая функцию get_incoming_messages каждую секунду или около того.
Проблема заключается в том, что при запуске программы в поле GTK_ENTRY появляется только куча мусорных символов, и моя консоль повторяет сообщение об ошибке "Pango-WARNING: неверная строка UTF-8 передана pango_layout_set_text()".
Я смог отправить UDP-сообщения без проблем, но схожу с ума, пытаясь понять, как их получить, даже если кажется, что это не должно быть так сложно!
Спасибо за любую помощь, вот мои функции:
static void open_listen_socket()
{
GInetAddress *localAddress;
GSocketAddress *localSocketAddress;
localAddress = g_inet_address_new_from_string("127.0.0.1");
guint16 listenPort = atoi(gtk_entry_get_text (GTK_ENTRY (listenPortField)));
localSocketAddress = g_inet_socket_address_new(localAddress, listenPort);
listenSocket = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, 17, NULL);
g_socket_bind (listenSocket, localSocketAddress, FALSE, NULL);
g_socket_set_blocking(listenSocket, FALSE);
g_socket_listen (listenSocket, NULL);
}
static int get_incoming_message()
{
gchar buffer[1024];
int input_length;
input_length = g_socket_receive(listenSocket, (gchar *)buffer, 1024, NULL, NULL);
gtk_entry_set_text (GTK_ENTRY (current_status_message_box), (const gchar *)buffer);
return 1;
}
Кроме того, если это поможет, мне нужно было добавить "return 1;" в конце get_incoming_message, потому что без него этот процесс, похоже, застрял внутри этой функции, хотя остальная часть приложения продолжала работать нормально.
/РЕДАКТИРОВАТЬ И ОБНОВИТЬ НИЖЕ*/
Хорошо, используя приведенный ниже совет, у меня все работает, но я столкнулся с новой проблемой. Похоже, что мой вызов g_socket_receive возвращает true при каждой итерации, печатая пустую строку, если сообщение не было отправлено. Это означает, что я вижу, что мои отправленные сообщения приходят, но они исчезают из GTK_ENTRY через доли секунды, поскольку они заменяются пустой строкой на следующей итерации.
static gboolean get_incoming_message()
{
gchar buffer[10] = {0};
GError *err = NULL;
if (g_socket_receive(listenSocket, (gchar *)buffer, 10, NULL, &err) > 0 );
{
printf("\n%s", buffer);
gtk_entry_set_text (GTK_ENTRY (current_status_message_box), (const gchar *)buffer);
return TRUE;
}
return FALSE;
}
Я не знаю, какие проверки использовать, чтобы определить разницу между реальным сообщением и этими пустыми строками! Это похоже на то, как если бы этот сокет получал бесконечный поток пустых данных каждый раз, когда законное сообщение не отправлялось. Имеет ли это смысл?
/Разобрался!/
Мне пришлось добавить инструкцию ELSE, чтобы дать ему что-то еще, когда не было данных, чтобы он не пытался написать пустую строку. Не уверен, что я это понимаю, поэтому я хотел бы получить объяснение, если у кого-то есть такое, но я снова в деле! Еще раз спасибо всем!
2 ответа
Есть несколько указателей для вашего рассмотрения:
- Всякий раз, когда функция предоставляет возможность использования
GError
пожалуйста, используйте это. Очень полезно узнать сообщение об ошибке - Проверьте возвращаемое значение функций, чтобы убедиться, что они выполнили то, для чего предназначались (уже указано Иоахимом)
- Используйте enum, когда доступно. В этом случае
GSocketProtocol
, Не использовать17
использованиеG_SOCKET_PROTOCOL_UDP
вместо этого, поскольку ваше приложение сломается, если значение enum изменится - UDP-сокеты на самом деле не "слушают", поэтому
g_socket_listen
вызов избыточен
Ниже приведен пример кода на основе того, что вы разместили в вашем распоряжении:
/* gcc -Wall -Wextra `pkg-config --cflags --libs glib-2.0 gio-2.0` gsock.c -o gsock */
#include <glib.h>
#include <gio/gio.h>
#include <stdio.h>
#define MAX_RECV 10
#define TIMEOUT_INTERVAL 1
static GSocket *listenSocket;
static GMainLoop *loop;
static gboolean
recv_msg(gpointer data)
{
(void)data;
static unsigned int count = 0;
gchar buffer[1024] ={0};
GError *err = NULL;
if( g_socket_receive(listenSocket, (gchar *)buffer, 1024, NULL, &err) > 0 )
{
printf("buff = %s\n", buffer);
}
else
{
printf(" Nothing posted in last %d sec (Error: %s)\n", TIMEOUT_INTERVAL, err->message);
g_error_free(err);
}
if(count++ < MAX_RECV)
return TRUE;
/* This is fugly!! :\ */
g_main_loop_quit(loop);
return FALSE;
}
static int
open_listen_socket(void)
{
GInetAddress *localAddress;
GSocketAddress *localSocketAddress;
GError *err = NULL; /* This is mandatory */
localAddress = g_inet_address_new_from_string("127.0.0.1");
guint16 listenPort = 31337; /* Can you recongnize this port? xD*/
localSocketAddress = g_inet_socket_address_new(localAddress, listenPort);
listenSocket = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &err);
if( NULL == listenSocket)
{
printf("\n Failed to create socket! Error: %s\n", err->message);
g_error_free(err);
return -1;
}
if( FALSE == g_socket_bind (listenSocket, localSocketAddress, FALSE, &err))
{
printf("\n Failed to bind! Error: %s\n", err->message);
g_error_free(err);
return -1;
}
g_socket_set_blocking(listenSocket, FALSE);
/* UDP socket don't "listen". Uncomment below to see the error message*/
/*
if(FALSE == g_socket_listen (listenSocket, &err))
{
printf("\n Failed to listen! Error: %s\n", err->message);
g_error_free(err);
}
*/
return 0;
}
int main(void)
{
g_type_init();
if(open_listen_socket() < 0)
{
printf("\n Socket creation went wrong!!\n");
}
else
{
loop = g_main_loop_new (NULL, TRUE);
g_timeout_add_seconds(TIMEOUT_INTERVAL, recv_msg, NULL);
g_main_loop_run(loop);
}
return 0;
}
Образец прогона:
Терминал 1:
$ ./gsock
Nothing posted in last 1 sec (Error: Error receiving data: Resource temporarily unavailable)
Nothing posted in last 1 sec (Error: Error receiving data: Resource temporarily unavailable)
Nothing posted in last 1 sec (Error: Error receiving data: Resource temporarily unavailable)
Nothing posted in last 1 sec (Error: Error receiving data: Resource temporarily unavailable)
Nothing posted in last 1 sec (Error: Error receiving data: Resource temporarily unavailable)
Nothing posted in last 1 sec (Error: Error receiving data: Resource temporarily unavailable)
buff = hello
buff = world
Nothing posted in last 1 sec (Error: Error receiving data: Resource temporarily unavailable)
Nothing posted in last 1 sec (Error: Error receiving data: Resource temporarily unavailable)
Nothing posted in last 1 sec (Error: Error receiving data: Resource temporarily unavailable)
Терминал 2:
$ nc 127.0.0.1 31337 -u
hello
world
^C
Надеюсь это поможет!
Проверьте строку, где вы получаете данные снова... Из какого сокета вы читаете? Разъем для прослушивания! Этот сокет используется только для приема новых соединений (через g_socket_accept
) функция.
g_socket_accept
возвращает новый сокет (который вы также должны сделать неблокирующим), который можно использовать для чтения и отправки.
Кроме того, вы действительно должны проверить возвращаемое значение из g_socket_receive
! В этом случае я могу почти поспорить, что он возвращается -1
за ошибку, но вы все равно "печатаете" буфер, который может содержать все что угодно.