On Sunday 11 December 2005 01:43, Travis Miller wrote: > Hello, > > I am trying to use GIOChannel in order to use sockets in a simple way (I > am trying to get notification on events like read and disconnect). > Anyway, here is the code that creates the GIOCHannel > > void > on_ListenButton_clicked (GtkButton *button, > gpointer user_data) > { > GtkWidget *text = lookup_widget(GTK_WIDGET(button), > "StatusText"); > > // create the listening socket > int sockfd, new_fd; > struct sockaddr_in my_addr; > struct sockaddr_in their_addr; > int sin_size; > > if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { > perror("socket"); > exit(1); > } > > my_addr.sin_family = AF_INET; > my_addr.sin_port = htons(1352); > my_addr.sin_addr.s_addr = INADDR_ANY; > bzero(&(my_addr.sin_zero), 8); > > if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct > sockaddr)) == -1) { > perror("bind"); > exit(1); > } > > > if (listen(sockfd, 5) == -1) { > perror("listen"); > exit(1); > } > gtk_entry_set_text(GTK_ENTRY(text), "Listening"); > > sin_size = sizeof(struct sockaddr_in); > if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, > &sin_size)) == -1) { > perror("accept"); > } > > // we got a socket so set text box > gtk_entry_set_text(GTK_ENTRY(text), "Connection accepted"); > > // now create GIOChannel from connection > GIOChannel *iochannel = g_io_channel_unix_new(new_fd); > > // now add to main event loop > GtkWidget *window = lookup_widget(GTK_WIDGET(button), > "MainWindow"); > g_io_add_watch(iochannel, G_IO_IN, (GIOFunc *) &ReceiveData, > (gpointer) window); > > > // now close the listener > close(sockfd); > > } > > The function g_io_watch() ties to the G_IO_IN (there is data to read on > the socket) event to the function ReceiveData that is defined as > > gboolean ReceiveData(GIOChannel *source, GIOCondition condition, > gpointer data) > { > gchar buf[500]; > int bytes_read; > GtkWidget *text = NULL; > GQuark quark; > GError *error = NULL; > gint sd; > > > > g_print("data received\n"); > text = lookup_widget(GTK_WIDGET(data), "StatusText"); > gtk_entry_set_text(GTK_ENTRY(text), "received data"); > > sd = g_io_channel_unix_get_fd(source); > > bytes_read = recv(sd, buf, 500, 0); > > if(bytes_read == -1) { > g_print("error\n"); > } > else { > buf[bytes_read] = '\0'; > g_print("buf = %s\n", buf); > text = lookup_widget(GTK_WIDGET(data), "ReceivedText"); > gtk_entry_set_text(GTK_ENTRY(text), buf); > } > > return TRUE; > } > > The problem is this. If the client closes the connection then I get a > flood of empty buffers and the ReceiveData() function is repeatedly > called. What could cause this weird behavior? I cannot see where you disconnect the callback. The easiest way to do that is to call g_io_channel_unref() on the iochannel pointer immediately after you have called g_io_add_watch() on it. g_io_channel_unix_new() returns a GIOChannel object with a reference count of one. g_io_add_watch() adds a further reference count - if you decrement it by 1, the callback will be disconnected and the relevant GSource object removed as soon either the callback returns FALSE or you call g_source_remove() on the return value of g_io_add_watch() - so detect the closing of the socket by the peer in the callback (read()/recv() returning 0 and/or the G_IO_HUP condition arising in your 'condition' variable) and return FALSE upon that occurring, or store the return value of g_io_add_watch() and call g_source_remove() on it. For the result you mention to occur, it appears therefore that specifying the G_IO_IN condition flag in g_io_add_watch() will cause the callback to be called even if the the socket is in error condition or the socket is closed, without actually specifying the G_IO_HUP or G_IO_ERR flags. Chris _______________________________________________ gtk-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-list