2014-01-09 3 views
1

Мне нужна ваша помощь.GMainLoop и TCP Listen thread blocking

У меня есть главный GMainLoop петля с прикрепленным таймаута обратного вызова:

MainLoop = g_main_loop_new(NULL, FALSE); 
g_timeout_add_seconds(Interval, TimeoutCallback, (gpointer) Rec); 
g_main_loop_run(MainLoop); 

И слушать сокет:

int ControlServer::GStart() 
{ 
    int listenfd; 
    GIOChannel *in; 
    socklen_t addr_len; 
    listenfd = TcpListen(host, port, &addr_len); 
    in = g_io_channel_unix_new(listenfd); 
    g_io_add_watch(in, G_IO_IN, (GIOFunc) Handler, (gpointer) Rec); 
    g_io_channel_unref(in); 
    return 0; 
} 

все средства хороши, и функция тайм-аута будет работать должным образом, пока ни один клиент не подключен к прислушивался гнездо. После подключения тайм-аут не работает все время, когда клиент подключается. Я думаю, что это связано с потоками, так как по документации GLib по умолчанию GMainContext выполняет все действия, выполняемые в одном потоке. И я изменил код с этим:

int ControlServer::GThStart() 
{ 
    int listenfd; 
    socklen_t addr_len; 
    GIOChannel *Channel; 
    GSource *Source; 
    GMainContext *Context; 

    listenfd = TcpListen(host, port, &addr_len); 
    Channel = g_io_channel_unix_new(listenfd); 
    Source = g_io_create_watch(Channel, G_IO_IN); 
    g_source_set_callback(Source, (GSourceFunc) Handler, (gpointer) Rec, NULL); 
    Context = g_main_context_new(); 
    g_source_attach(Source, Context); 
    g_source_unref(Source); 
    return 0; 
} 

Но теперь сокет прислушался, но не все клиенты не могут подключиться к нему и функции обработчика никогда не называется.

Handler код ниже:

bool ControlServer::Handler(GIOChannel *in, GIOCondition condition, gpointer data) 
{ 
    Recorder *Rec = (Recorder *) data; 
    struct sockaddr_storage income; 
    int insock, newsock; 
    socklen_t income_len; 
    struct sockaddr peer; 
    socklen_t size; 
    Access *access; 

    insock = g_io_channel_unix_get_fd(in); 
    income_len = sizeof(income); 
    newsock = accept(insock, (struct sockaddr *) &income, &income_len); 
    size = sizeof(peer); 
    getpeername(newsock, &peer, &size); 
    struct sockaddr_in *ipv4 = (struct sockaddr_in *) &peer; 
    access = new Access(newsock, ipv4, MAXN); 

    access->Cycle(Rec); 

    delete access; 
    return true; 
} 

Класс права установить флажок «Access» клиента и выполнения протокола обмена по реализации бесконечного цикла в то время как клиент или сервер не тесная связь.

do 
    { 
     result = DoCycle(Rec); 
     sprintf(str, "DEBUG: DoCycle(Rec) returns '%d'\n", result); 
     AppendLog(str, class_name, DEBUG); 
    } while (result != -1); 

DoCycle() возвращает '-1' только при закрытом соединении или обмене данными об ошибках через TCP.

Что не так? Спасибо!

+0

Что Handler выглядит? – nemequ

+0

Я только что добавил код для Handler и некоторые объяснения. – Xuch

ответ

1

Проблема в функции int ControlServer::GThStart(), вы должны добавить GSource к GMainContext вашего GMainLoop, а не новый контекст, попробуйте его:

g_source_attach(Source,g_main_loop_get_context(MainLoop)); 
Смежные вопросы