【问题标题】:Receiving garbage from GSocket从 GSocket 接收垃圾
【发布时间】:2012-02-16 05:39:58
【问题描述】:

我正在使用以下函数来创建和打开 GSocket,然后侦听 UDP 消息以显示在 GTK_ENTRY 字段中。调用 open_listen_socket 函数,然后我有一个超时函数,每隔一秒左右调用一次 get_incoming_messages 函数。

问题是,当我启动程序时,我只在 GTK_ENTRY 字段中显示一堆垃圾字符,并且我的控制台重复错误消息“Pango-WARNING: Invalid UTF-8 string passing to 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 语句,以便在没有数据时给它做其他事情,以防止它尝试写入空行。不确定我是否理解这一点,所以如果有人有解释,我很想知道,但我又回来了!再次感谢大家!

【问题讨论】:

  • 收到的文本,是否包含终止符'\0'?也许你需要添加它?
  • 不确定你的意思。即使没有发送任何文本,我也会收到奇怪的消息。我一启动应用程序,它就会开始弹出。

标签: c linux glib


【解决方案1】:

有几个指针供您考虑:

  1. 每当功能提供使用GError的便利时,请使用它。找出错误信息非常有帮助
  2. 检查函数的返回值以确保它们已完成预期的工作(Joachim 已经指出)
  3. 在可用时使用枚举。在这种情况下GSocketProtocol。不要使用17 而是使用G_SOCKET_PROTOCOL_UDP,因为如果枚举值发生更改,您的应用程序将会中断
  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

希望这会有所帮助!

【讨论】:

  • 非常感谢您的详细回答!在这和 Joachim 的响应之间,我认为我的主要问题(除了不使用错误处理之外)是使我的套接字成为“侦听”套接字,然后我如何处理套接字上的内容的打印。一旦我今晚可以测试我的更改,我会将这些答案标记为正确。再次感谢!
  • 这是我发现的第一个使用 glib(特别是套接字)的工作示例代码。非常感谢。
【解决方案2】:

再次检查您接收数据的行...您从哪个套接字读取? 监听套接字!该套接字仅用于接受新连接(通过g_socket_accept)函数。

g_socket_accept 返回一个新的套接字(您还必须使其非阻塞),可用于读取和发送。

另外,你真的应该检查来自g_socket_receive 的返回值!在这种情况下,我几乎可以打赌它会因为错误返回 -1,但无论如何你“打印”了可以包含任何内容的缓冲区。

【讨论】:

  • 感谢您的澄清!我无法找到任何关于将套接字用于我的项目之类的示例或明确信息,而我不需要任何实际的“连接”。
猜你喜欢
  • 2019-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
  • 2014-07-31
  • 1970-01-01
  • 2018-12-30
  • 1970-01-01
相关资源
最近更新 更多