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. At this point G_IO_OUT is surely
ok, the mainloop thread returns from poll and sends one byte to server in
callback. Then the program watches
for G_IO_IN. mainloop thread will block. Then the program sleeps
for a while, and watches for G_IO_OUT. Here, I wish the mainloop
thread to return from poll with G_IO_OUT event. However, 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); } |