Получение мусора от 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 ответа

Решение

Есть несколько указателей для вашего рассмотрения:

  1. Всякий раз, когда функция предоставляет возможность использования GError пожалуйста, используйте это. Очень полезно узнать сообщение об ошибке
  2. Проверьте возвращаемое значение функций, чтобы убедиться, что они выполнили то, для чего предназначались (уже указано Иоахимом)
  3. Используйте enum, когда доступно. В этом случае GSocketProtocol, Не использовать 17 использование G_SOCKET_PROTOCOL_UDP вместо этого, поскольку ваше приложение сломается, если значение enum изменится
  4. 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 за ошибку, но вы все равно "печатаете" буфер, который может содержать все что угодно.

Другие вопросы по тегам