I write a client network program using GIOChannel and
GMainLoop on windows. The server program is a simple sink server, which eats
all input. The client program first connects server, then watches
for G_IO_IN and G_IO_OUT and creates a thread which do g_main_loop_run. Surely G_IO_OUT is ok, the mainloop thread returns
from poll and sends one byte to server in callback. Then watches for G_IO_IN. mainloop thread will block. Then sleep for a while, watches for G_IO_OUT. I wish the mainloop thread to return from poll with
G_IO_OUT event. However, now mainloop will block instead of returning
from poll. I think the problem is FD_WRITE will not signaled
again until send returns WSAEWOULDBLOCK on windows. Is this a bug of GMainLoop? Thanks. The client program source code: ----------------------------------------------------------------------- #include <winsock2.h> #include "glib.h" guint source_id; GMutex *mutex; GCond *cond; gboolean recv_cb (GIOChannel *source, GIOCondition
condition, gpointer
data) { g_assert_not_reached (); } gboolean send_cb (GIOChannel *source, GIOCondition
condition, gpointer
data) { gboolean is_second = (gboolean) data; GIOStatus status; gsize bytes_written; gchar c = 'T'; status = g_io_channel_write_chars (source,
&c, 1, &bytes_written, NULL); g_print ("%s send_cb write char, status:
%d.\n",
(is_second ? "Second" : "First"),
status); g_source_remove (source_id); source_id = g_io_add_watch (source,
G_IO_IN | G_IO_ERR,
recv_cb,
NULL); g_mutex_lock (mutex); g_cond_signal (cond); g_mutex_unlock (mutex); return (TRUE); } int main (int argc, char **argv) { WSADATA wsa_data; SOCKET s; struct sockaddr_in addr; gint addrlen = sizeof (addr); GIOChannel *channel; GMainLoop *loop; GThread *thread; g_assert (WSAStartup(0x0202, &wsa_data) ==
0); g_thread_init (NULL); mutex = g_mutex_new (); cond = g_cond_new (); s = socket (AF_INET, SOCK_STREAM, 0); g_assert (s != INVALID_SOCKET); g_assert (WSAStringToAddress
("155.69.149.175:5555", AF_INET, NULL, (PSOCKADDR)&addr, &addrlen)
!= SOCKET_ERROR); g_assert (connect (s, (struct sockaddr *)
&addr, sizeof (addr)) != SOCKET_ERROR); channel = g_io_channel_win32_new_socket (s); loop = g_main_loop_new (NULL, FALSE); g_assert (loop); thread = g_thread_create ((GThreadFunc)
g_main_loop_run,
loop,
TRUE,
NULL); g_assert (thread); g_mutex_lock (mutex); source_id = g_io_add_watch (channel,
G_IO_IN | G_IO_ERR | G_IO_OUT,
send_cb,
(gpointer) FALSE); g_cond_wait (cond, mutex); g_mutex_unlock (mutex); g_usleep (500000); g_source_remove (source_id); g_usleep (500000); g_mutex_lock (mutex); source_id = g_io_add_watch (channel,
G_IO_IN | G_IO_ERR | G_IO_OUT,
send_cb,
(gpointer) TRUE); g_cond_wait (cond, mutex); g_mutex_unlock (mutex); g_main_loop_quit (loop); g_thread_join (thread); return (0); } |