2012-02-16 39 views
0

我正在使用下面的函數來創建並打開一個GSocket,然後監聽UDP消息以顯示在GTK_ENTRY字段中。 open_listen_socket函數被調用,然後在每秒鐘之後,我有一個超時函數調用get_incoming_messages函數。從GSocket接收垃圾

問題是,當我啓動程序時,我只能看到一堆顯示在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; 

} 

而且,如果它有助於在所有,我不得不添加了「返回1;」在get_incoming_message的末尾,因爲沒有它,即使應用程序的其餘部分繼續正常工作,該進程似乎仍然卡在該函數內。

/編輯和更新下 */

OK,請用下面的建議我有事情的工作,但我創下了新的問題。看起來我對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

收到的文字是否包含終止的''\ 0''?也許你需要添加它? – 2012-02-16 06:33:53

+0

不確定你的意思。即使沒有發送任何文本,我也會收到奇怪的消息。一旦我啓動應用程序,它就會開始彈出。 – DrRocket 2012-02-16 06:39:30

回答

3

有你的考慮幾個要點:

  1. 每當功能提供的設施,使用GError請利用。找出錯誤信息是非常有幫助的
  2. 檢查函數的返回值以確保它們完成了它們的目標(已經由Joachim指出)
  3. 使用enum(如果可用)。在這種情況下,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 

希望這有助於!

+0

非常感謝你的詳細解答!這和勒夫的迴應之間,我想我的主要問題(除了不使用錯誤處理)分別使我的插座「聽」插座,再怎麼我處理了後來在插座上印刷。一旦我能夠測試我今晚的變化,我會將這些答案標記爲正確的。再次感謝! – DrRocket 2012-02-16 17:52:26

+0

這是使用油嘴(和具體地插座),我已經找到了第一工作示例的代碼。謝謝一堆。 – Kurt 2016-03-11 22:51:44

1

檢查您再次收到數據的線......您讀取哪個套接字? 監聽 socket!該套接字僅用於接受新連接(通過g_socket_accept)功能。

g_socket_accept返回一個新的套接字(您也必須做出非阻塞),它可以用於讀取和發送。

此外,你應該真的從g_socket_receive檢查返回值!在這種情況下,我幾乎可以打賭它返回一個錯誤返回-1,但是您仍然「打印」緩衝區,可以包含任何東西。

+0

謝謝你的澄清!我一直沒能找到任何實例或使用插座的東西,像我的項目,我從來不需要任何實際明確的信息「連接」。 – DrRocket 2012-02-16 17:47:43