根据《GTK编程范例》修改的一个聊天室程序。急急急

软件和网站开发以及相关技术探讨
回复
头像
mofi
帖子: 35
注册时间: 2012-11-20 15:42
系统: ubuntu/windows7

根据《GTK编程范例》修改的一个聊天室程序。急急急

#1

帖子 mofi » 2014-05-21 23:29

这个是nae6taiyie0T仁兄修改的程序。但是运行后,如果关闭一个客户端的话,所有的客户端都会退出,是什么问题哈,帮忙解决下

代码: 全选


client.c
#include<gtk/gtk.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>

#include "chatroom.h"


gint sd;
struct sockaddr_in s_in;
gchar username[NAME_SIZE];
gchar buf[BUF_SIZE];
// FIXME: why 1048?
//gchar get_buf[1048];
gchar get_buf[BUF_SIZE];
gboolean isconnected = FALSE;

static GtkWidget *text;
static GtkTextBuffer *buffer;
static GtkWidget *message_entry;
static GtkWidget *name_entry;
static GtkWidget *login_button;

void get_message(void) {
   GtkTextIter iter;
   gchar get_buf[BUF_SIZE];
   gchar buf[BUF_SIZE];
   while(read(sd, buf, BUF_SIZE) != -1) {
      sprintf(get_buf, "%s", buf);
     
      //gdk_threads_enter();
      gtk_text_buffer_get_end_iter(buffer, &iter);
      gtk_text_buffer_insert(buffer, &iter, get_buf, -1);
      //gdk_threads_leave();
   }
}

void on_destroy(GtkWidget *widget, GdkEvent *event, gpointer data) {
   sprintf(username, "guest");
   if(do_connect() == TRUE) {
      gtk_widget_set_sensitive(login_button, FALSE);
      g_thread_new("get_message", (GThreadFunc)get_message, NULL);
   }
   gtk_widget_destroy(widget);
}

void on_button_clicked(GtkButton *button, gpointer data) {
   const gchar *name;
   name = gtk_entry_get_text(GTK_ENTRY(name_entry));
   sprintf(username, "%s", name);

   if(do_connect()) {
      gtk_widget_set_sensitive(login_button, FALSE);
      g_thread_new("get_message", (GThreadFunc)get_message, NULL);
   }
    
   gtk_widget_destroy(data);
}

void create_win(void) {
   GtkWidget *win, *vbox;
   GtkWidget *button;   
   win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_window_set_title(GTK_WINDOW(win), "输入用户名");
   gtk_container_set_border_width(GTK_CONTAINER(win), 10);
   g_signal_connect(G_OBJECT(win), "delete_event",
                    G_CALLBACK(on_destroy), NULL);
   gtk_window_set_modal(GTK_WINDOW(win), TRUE);
   gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER);

   vbox = gtk_vbox_new(FALSE, 0);
   gtk_container_add(GTK_CONTAINER(win), vbox);
   
   name_entry = gtk_entry_new();
   gtk_box_pack_start(GTK_BOX(vbox), name_entry, TRUE, TRUE, 5);
   button = gtk_button_new_from_stock(GTK_STOCK_OK);
   g_signal_connect(G_OBJECT(button), "clicked",
                    G_CALLBACK(on_button_clicked), win);
   gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 5);
   gtk_widget_show_all(win);
}

gboolean do_connect(void) {
   GtkTextIter iter;
   gint slen;
   sd = socket(AF_INET, SOCK_STREAM, 0);
   if(sd < 0) {
      gtk_text_buffer_get_end_iter(buffer, &iter);
      gtk_text_buffer_insert(buffer, &iter, "打开套接字时出错!\n", -1);
      return FALSE;
   }
   s_in.sin_family = AF_INET;
   s_in.sin_port = OURPORT;
   slen = sizeof(s_in);
   if(connect(sd, &s_in, slen) < 0) {
      gtk_text_buffer_get_end_iter(buffer, &iter);
      gtk_text_buffer_insert(buffer, &iter, "连接服务器时出错!\n", -1);
      return FALSE;
   } else {
      gtk_text_buffer_get_end_iter(buffer, &iter);
      gtk_text_buffer_insert(buffer, &iter, username, -1);
      gtk_text_buffer_get_end_iter(buffer, &iter);
      gtk_text_buffer_insert(buffer, &iter, "\n成功与服务器连接..\n", -1);
      write(sd, username, NAME_SIZE);
      isconnected = TRUE;
      return TRUE;
   }
}

void on_send(GtkButton *button, gpointer data) {
   const char *message;

   if(isconnected == FALSE) {
     return;
   }
   message = gtk_entry_get_text(GTK_ENTRY(message_entry));
   sprintf(buf, "%s\n", message);
   write(sd, buf, BUF_SIZE);
   gtk_entry_set_text(GTK_ENTRY(message_entry), "");
}

void on_login(GtkWidget *button, gpointer data) {
   create_win();
}

void on_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) {
   close(sd);
   gtk_main_quit();
}

int main(int argc, char *argv[]) {
   GtkWidget *window;
   GtkWidget *vbox, *hbox, *button, *label, *view;

   gtk_init(&argc, &argv);

   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_window_set_title(GTK_WINDOW(window), "客户端");
   gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
   gtk_container_set_border_width(GTK_CONTAINER(window), 5);
   g_signal_connect(G_OBJECT(window), "delete_event",
                    G_CALLBACK(on_delete_event), NULL);

   vbox = gtk_vbox_new(FALSE, 0);
   gtk_container_add(GTK_CONTAINER(window), vbox);

   hbox = gtk_hbox_new(FALSE, 0);
   gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
   label = gtk_label_new("点击登陆按钮连接服务器");
   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
   login_button = gtk_button_new_with_label("登录");
   gtk_box_pack_start(GTK_BOX(hbox), login_button, FALSE, FALSE, 5);
   g_signal_connect(G_OBJECT(login_button), "clicked",
                    G_CALLBACK(on_login), NULL);

   view = gtk_scrolled_window_new(NULL, NULL);
   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(view),
                                  GTK_POLICY_AUTOMATIC,
                                  GTK_POLICY_AUTOMATIC);
   text = gtk_text_view_new();
   gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 0);
   gtk_container_add(GTK_CONTAINER(view), text);
   buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));

   hbox = gtk_hbox_new(FALSE, 0);
   gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);

   message_entry = gtk_entry_new();
   gtk_box_pack_start(GTK_BOX(hbox), message_entry, TRUE, TRUE, 0);
   g_signal_connect(G_OBJECT(message_entry), "activate",
                    G_CALLBACK(on_send), NULL);

   button = gtk_button_new_with_label("发送");
   gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
   g_signal_connect(G_OBJECT(button), "clicked",
                    G_CALLBACK(on_send), NULL);

   gtk_widget_show_all(window);
   gtk_main();

   return 0;
}









server.c


#include<glib.h>
#include<stdio.h>
#include<fcntl.h>
#include<signal.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/time.h>
#include<unistd.h>
#include<netdb.h>
#include<netinet/in.h>

#include "chatroom.h"


struct _client{
  gint sd;
  gboolean in_use;
  gchar name[NAME_SIZE];
  gchar buf[BUF_SIZE];
};
typedef struct _client client;
client users[MAX_USERS];

void do_service(gpointer id) {
  gint j;
  char tobuf[BUF_SIZE];
  gint uid = GPOINTER_TO_INT(id);

  while(read(users[uid].sd, users[uid].buf, BUF_SIZE) != -1) {
    sprintf(tobuf, "%s:%s\n", users[uid].name, users[uid].buf);
    for(j= 0; j < MAX_USERS; j++) {
      if(users[j].in_use) {
        write(users[j].sd,tobuf, BUF_SIZE);
        g_print("%s", tobuf);
      }
    }
  }
  users[uid].in_use = FALSE;
  close(users[uid].sd);
}

int main(int argc, char *argv[]) {
  int sd, newsd;
  struct sockaddr_in sin;
  socklen_t slen;
  gint count = 0;
  gint flags;
  gchar buf[BUF_SIZE];
  gint i;
  
  sd = socket(AF_INET, SOCK_STREAM, 0);
  if(sd == -1) {
    g_print("create socket error!\n");
    return -1;
  }

  sin.sin_family = AF_INET;
  sin.sin_port = OURPORT;
  slen = sizeof(struct sockaddr_in);
  
  if(bind(sd, &sin, slen) < 0) {
    g_print("bind erro!\n");
    return -1;
  }

  if(listen(sd, 8) < 0) {
    g_print("listen error!\n");
    return -1;
  }

  for(i = 0; i < MAX_USERS; i++) {
    users[i].in_use = FALSE;
  }

  flags = fcntl(sd, F_GETFL);
  fcntl(sd, F_SETFL, flags&~O_NDELAY);

  while(TRUE) {
    newsd = accept(sd, &sin, &slen);
    if(newsd == -1) {
      g_print("accept error!\n");
      break;
    } else {
      if(count >= MAX_USERS) {
        sprintf(buf, "用户数量过多服务器不能连接。\n");
        write(newsd, buf, BUF_SIZE);
        close(newsd);
      } else {
        flags = fcntl(users[i].sd, F_GETFL);
        fcntl(users[i].sd, F_SETFL, O_NONBLOCK);
        users[count].sd = newsd;
        users[count].in_use = TRUE;
        read(newsd, users[count].name, NAME_SIZE);
        g_thread_new("do_server",
                     (GThreadFunc)do_service,
                     GINT_TO_POINTER(count));
        count++;
      }
    }
  }
  printf("sd is never closed!\n");
  close(sd);

  return 0;
}





classroom.h
#ifndef _CHAT_ROOTM_H_
#define _CHAT_ROOTM_H_

#define OURPORT 8088
#define MAX_USERS 8
#define NAME_SIZE 64
#define BUF_SIZE 1024


#endif


头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

Re: 根据《GTK编程范例》修改的一个聊天室程序。急急急

#2

帖子 eexpress » 2014-05-22 9:09

on_destroy的时候,应该条件判断处理。猜想。
● 鸣学
回复