先是做完的效果图:
server.c
1 /* 服务器端 server.c */ 2 #include <glib.h> 3 #include <stdio.h> 4 #include <fcntl.h> 5 #include <signal.h> 6 #include <sys/socket.h> 7 #include <sys/types.h> 8 #include <sys/time.h> 9 #include <unistd.h> 10 #include <netdb.h> 11 #include <netinet/in.h> 12 #include <arpa/inet.h> 13 #define MAX_USERS 800 //最大访问人数 14 15 //定义用户数据结构 16 struct _client { 17 gint sd; 18 gboolean in_use; 19 gchar name[64]; 20 gchar buf[1024]; 21 }; 22 typedef struct _client client; 23 24 //定义用户数据区 25 client user[MAX_USERS]; 26 //定义服务线程 27 void do_service (gpointer id){ 28 gint j; 29 char tobuf[1024]; 30 while(read(user[GPOINTER_TO_INT(id)].sd,user[GPOINTER_TO_INT(id)].buf,1024)!=-1) 31 { 32 sprintf(tobuf,"%s:%s\n",user[GPOINTER_TO_INT(id)].name, 33 user[GPOINTER_TO_INT(id)].buf); 34 for(j=0; j<MAX_USERS; j++) { 35 if(user[j].in_use) 36 { 37 write(user[j].sd,tobuf,1024); 38 //g_print("%s",tobuf); 39 } 40 } 41 } 42 // 43 user[GPOINTER_TO_INT(id)].in_use = FALSE; 44 close(user[GPOINTER_TO_INT(id)].sd); 45 exit(0); 46 47 } 48 int main(int argc, char* argv[]) 49 { 50 gint sd, newsd; 51 struct sockaddr_in *sin; 52 gint slen; 53 gint count = 0; 54 gint flags; 55 gchar buf[1024]; 56 gchar tobuf[1024]; 57 gint length,i,j; 58 if(!g_thread_supported()) 59 g_thread_init(NULL); 60 else 61 g_print("thread not supported\n"); 62 63 sd = socket(AF_INET,SOCK_STREAM,0); //1.......创建套接子 64 if(sd == -1) 65 { 66 g_print("create socket error!\n"); 67 return -1; 68 } 69 sin = g_new(struct sockaddr_in,1); 70 sin->sin_family = AF_INET; 71 sin->sin_port = htons(1234); 72 slen = sizeof(struct sockaddr_in); 73 sin->sin_addr.s_addr=inet_addr("127.0.0.1"); 74 75 if(bind(sd,(struct sockaddr*)sin,slen)<0) //2......绑定 76 { 77 g_print("bind error!\n"); 78 return -1; 79 } 80 if(listen(sd,8)<0) //3......开启监听 81 { 82 g_print("listen error!\n"); return -1; 83 } 84 for(i=0; i<MAX_USERS; i++) //判断访问人数 85 user[i].in_use = FALSE; 86 flags = fcntl(sd,F_GETFL); 87 fcntl(sd,F_SETFL,flags&~O_NDELAY); 88 for(;;) 89 { 90 newsd = accept(sd,sin,&slen); //4....接收 91 if(newsd == -1){ 92 g_print("accept error!\n"); 93 break; 94 } 95 else 96 { 97 if(count >= MAX_USERS) 98 { 99 sprintf(buf,"用户数量过多服务器不能连接。\n"); 100 write(newsd,buf,1024); 101 close(newsd); 102 } 103 else 104 { 105 flags = fcntl(user[i].sd,F_GETFL); 106 fcntl(user[i].sd,F_SETFL,O_NONBLOCK); 107 user[count].sd = newsd; 108 user[count].in_use = TRUE; 109 read(newsd,user[count].name,64); 110 // 创建为用户服务的线程 111 g_thread_create((GThreadFunc)do_service, 112 113 (gpointer)count,TRUE,NULL); 114 count++; 115 } 116 } 117 }// 118 for(;;) 119 close(sd); 120 g_free(sin); 121 }
client.c
1 /* 客户端 client.c */ 2 #include <gtk/gtk.h> 3 #include<stdio.h> 4 #include<string.h> 5 #include<stdlib.h> 6 #include <sys/types.h> 7 #include <sys/socket.h> 8 #include <netinet/in.h> 9 #include</usr/include/mysql/mysql.h> 10 #define OURPORT 8088 //定义端口号 11 #define MAXLINE 800 12 13 static GtkWidget *text1; 14 static GtkWidget *text2; 15 static GtkWidget *login; 16 static GtkWidget *entry_id; 17 static GtkWidget *entry_pwd; 18 static GtkWidget *regwindow; 19 20 static GtkWidget *reg_entry1; 21 static GtkWidget *reg_entry2; 22 23 static GtkWidget *window1;//聊天室主窗口 24 static GtkWidget *win;//昵称登录窗口 25 static GtkWidget *text_view; 26 27 static GtkTextBuffer *buffer; //显示对话内容的文本显示缓冲区 28 static GtkTextBuffer *buffer1; 29 static GtkTextBuffer *buffer2; 30 static GtkWidget *textview1; //显示输入消息的单行录入控件 31 static GtkWidget *name_entry;//输入用户名的单行录入控件 32 static GtkWidget *login_button; //登录按钮 33 void btn_cal_clicked(); 34 void on_send (GtkButton* button, gpointer data) ; 35 void update_widget_bg(GtkWidget * widget, gchar * img_file); 36 37 gint sd; //套接字句柄 38 struct sockaddr_in s_in; //套接字数据结构 39 gchar username[64]; //用户名 40 gchar buf[1024]; //写缓冲区 41 gchar get_buf[1048]; //读缓冲区 42 gboolean isconnected = FALSE; // 定义逻辑值表示是否连接 43 44 MYSQL_RES *rs; 45 MYSQL_ROW row; 46 MYSQL_RES *exe_sql(char sql[MAXLINE]) 47 { 48 const char *host = "localhost"; 49 const char *user = "root"; 50 const char *pass = ""; 51 const char *db = "talk"; 52 53 /* 定义mysql变量 */ 54 MYSQL_RES *result; 55 MYSQL * mysql; 56 if(!(mysql=mysql_init(NULL))) 57 { 58 printf("mysql_init wrong!"); 59 mysql_close(mysql); 60 exit(0); 61 } 62 /* 连接数据库 */ 63 if (!mysql_real_connect(mysql, host, user, pass, db, 3306, NULL, 0)) 64 { 65 printf("connect wrong!"); 66 mysql_close(mysql); 67 exit(0); 68 } 69 printf("%s\n",sql); 70 if(mysql_query(mysql,sql)) 71 { 72 printf("mysql_query_wrong!"); 73 mysql_close(mysql); 74 exit(0); 75 } 76 result = mysql_store_result(mysql); /* 获取查询结果 */ 77 return result; 78 } 79 //socket通信 80 void get_message(void) 81 { 82 GtkTextIter iter; 83 gchar get_buf[1024]; 84 gchar buf[1024]; 85 while(read(sd,buf,1024) != -1) // 只要读取数据成功就循环执行 86 { 87 sprintf(get_buf,"%s",buf); 88 printf("%s\n",buf); 89 gdk_threads_enter(); //进入 90 gtk_text_buffer_get_end_iter(buffer,&iter); 91 gtk_text_buffer_insert(buffer,&iter,get_buf,-1);//显示读取的数据 92 gdk_threads_leave(); //离开 93 } 94 } 95 // 连接多人聊天服务器 96 gboolean do_connect(void) 97 { 98 GtkTextIter iter; 99 gint slen; 100 sd = socket(AF_INET,SOCK_STREAM,0);//创建 101 printf("%d\n",sd); 102 if(sd < 0) 103 { 104 gtk_text_buffer_get_end_iter(buffer,&iter); 105 gtk_text_buffer_insert(buffer,&iter,"打开套接字时出错!\n",-1); 106 return FALSE; 107 } 108 s_in.sin_family = AF_INET; 109 s_in.sin_port = htons(1234); 110 slen = sizeof(s_in); 111 if(connect(sd,&s_in,slen) < 0) // 112 { 113 gtk_text_buffer_get_end_iter(buffer,&iter); 114 gtk_text_buffer_insert(buffer,&iter,"连接服务器时出错!\n",-1); 115 return FALSE; 116 } 117 else 118 { 119 120 gtk_text_buffer_get_end_iter(buffer,&iter); 121 gtk_text_buffer_insert(buffer,&iter,username,-1); 122 gtk_text_buffer_get_end_iter(buffer,&iter); 123 gtk_text_buffer_insert(buffer,&iter,"\n成功与服务器连接....\n",-1); 124 // 125 write(sd,username,64);//向服务器发送用户名// 126 isconnected = TRUE; 127 return TRUE; 128 } 129 } 130 void on_send (GtkButton* button, gpointer data) 131 { 132 //向服务器发送数据 133 const char* message; 134 GtkTextIter start; 135 GtkTextIter end; 136 char sql[MAXLINE]; 137 if(isconnected==FALSE) 138 return; 139 buffer1=gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview1)); 140 gtk_text_buffer_get_start_iter(buffer1,&start); 141 gtk_text_buffer_get_end_iter(buffer1,&end); 142 message=gtk_text_buffer_get_text(buffer1,&start,&end,TRUE); 143 sprintf(buf,"%s\n",message); 144 write(sd,buf,1024);//发送 145 sprintf(sql,"insert into history (user,message,date) values (‘%s‘,‘%s‘,now())",username,message); 146 147 rs = exe_sql(sql); 148 gtk_text_buffer_set_text(buffer1,"",-1);////清除文字 149 150 } 151 void on_login(GtkWidget *button, gpointer data) 152 { 153 //点击登录按钮时执行 154 create_win(); 155 } 156 void cls()//清屏 157 { 158 gtk_text_buffer_set_text(buffer,"",-1); 159 } 160 void history() 161 { 162 int rows_num; 163 int count; 164 GtkBuilder *gb; 165 //查看历史窗口 166 GtkWidget *history_win;//查看聊天历史界面 167 GtkWidget *history_view; 168 char *sql[MAXLINE]; 169 gb=gtk_builder_new(); 170 gtk_builder_add_from_file(gb,"history.glade",NULL); 171 history_win=GTK_WIDGET(gtk_builder_get_object(gb,"history_win")); 172 history_view=GTK_WIDGET(gtk_builder_get_object(gb,"history_view")); 173 update_widget_bg(history_win, "ico/bg.jpg"); 174 gtk_widget_show(GTK_WIDGET(history_win)); 175 //显示数据 176 strcpy(sql,"select * from history where date <=now() and date >=now()-interval 5 minute"); 177 rs=exe_sql(sql); 178 printf("%s\n",sql); 179 rows_num=mysql_num_rows(rs); 180 181 for(count=0;count<rows_num;count++) 182 { 183 GtkTextIter end; 184 row=mysql_fetch_row(rs); 185 buffer1 = gtk_text_view_get_buffer(GTK_TEXT_VIEW(history_view)); 186 gtk_text_buffer_get_end_iter(buffer1,&end); 187 gtk_text_buffer_insert(buffer1, &end, row[1], -1); 188 gtk_text_buffer_insert(buffer1, &end, " : ", -1); 189 gtk_text_buffer_insert(buffer1, &end, row[2], -1); 190 gtk_text_buffer_insert(buffer1, &end, " ", -1); 191 gtk_text_buffer_insert(buffer1, &end, row[3], -1); 192 gtk_text_buffer_insert(buffer1, &end, "\n", -1); 193 194 } 195 } 196 //当点击登录窗口的登录按钮时执行 197 void on_button_clicked(GtkButton *button, gpointer data) 198 { 199 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)); 200 gtk_text_buffer_set_text(buffer, "Hello ", -1); 201 gchar *name; 202 name = gtk_entry_get_text(GTK_ENTRY(name_entry)); 203 204 sprintf(username,"%s",name); 205 206 if(do_connect()) 207 { 208 gtk_widget_set_sensitive(login_button,FALSE); 209 g_thread_create((GThreadFunc)get_message,NULL,FALSE,NULL); 210 } 211 gtk_widget_destroy(data); 212 } 213 214 //当前关闭登录窗口时执行 215 void on_destroy(GtkWidget *widget, GdkEvent *event, gpointer data) 216 { 217 sprintf(username,"guest"); 218 if(do_connect()==TRUE) 219 { 220 gtk_widget_set_sensitive(login_button,FALSE); 221 g_thread_create((GThreadFunc)get_message,NULL,FALSE,NULL); 222 } 223 gtk_widget_destroy(widget); 224 } 225 //背景图片的显示功能 226 void update_widget_bg(GtkWidget * widget, gchar * img_file) 227 { 228 GtkStyle *style; 229 GdkPixbuf *pixbuf; 230 GdkPixmap *pixmap; 231 gint width, height; 232 233 pixbuf = gdk_pixbuf_new_from_file(img_file, NULL); 234 width = gdk_pixbuf_get_width(pixbuf); 235 height = gdk_pixbuf_get_height(pixbuf); 236 pixmap = gdk_pixmap_new(NULL, width, height, 24); 237 gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, NULL, 0); 238 style = gtk_style_copy(GTK_WIDGET(widget)->style); 239 if (style->bg_pixmap[GTK_STATE_NORMAL]) 240 g_object_unref(style->bg_pixmap[GTK_STATE_NORMAL]); 241 style->bg_pixmap[GTK_STATE_NORMAL] = g_object_ref(pixmap); 242 style->bg_pixmap[GTK_STATE_ACTIVE] = g_object_ref(pixmap); 243 style->bg_pixmap[GTK_STATE_PRELIGHT] = g_object_ref(pixmap); 244 style->bg_pixmap[GTK_STATE_SELECTED] = g_object_ref(pixmap); 245 style->bg_pixmap[GTK_STATE_INSENSITIVE] = g_object_ref(pixmap); 246 gtk_widget_set_style(GTK_WIDGET(widget), style); 247 g_object_unref(style); 248 } 249 void btn_cal(GtkWidget *dialog,gpointer data) 250 { 251 gtk_widget_destroy(win); 252 return FALSE; 253 } 254 void create_win(void) 255 { //昵称窗口 256 GtkBuilder *gb; 257 GtkWidget *btn_ok; 258 gb=gtk_builder_new(); 259 gtk_builder_add_from_file(gb,"log.glade",NULL); 260 win=GTK_WIDGET(gtk_builder_get_object(gb,"win")); 261 name_entry=GTK_WIDGET(gtk_builder_get_object(gb,"name_entry")); 262 btn_ok=GTK_WIDGET(gtk_builder_get_object(gb,"btn_ok")); 263 update_widget_bg(win, "ico/bg.jpg"); 264 gtk_widget_show(GTK_WIDGET(win)); 265 g_signal_connect(GTK_OBJECT(btn_ok),"clicked",G_CALLBACK(on_button_clicked),win); 266 } 267 //聊天室关闭按钮 268 void button1_clicked() 269 { 270 close(sd);//关闭 271 gtk_main_quit(); 272 } 273 /* 弹出对话框代码开始*/ 274 void show_info(char *msgtip) 275 { 276 GtkWidget *dialog; 277 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, msgtip); 278 gtk_window_set_title(GTK_WINDOW(dialog), "Information"); 279 gtk_dialog_run(GTK_DIALOG(dialog)); 280 gtk_widget_destroy(dialog); 281 } 282 /*glade主界面*/ 283 #define w_(builder,type,name) name=GTK_##type(gtk_builder_get_object(builder,#name)) 284 GtkBuilder* gtk_load_glade(gchar* filename) 285 286 { 287 288 GtkBuilder *gb; 289 290 gb=gtk_builder_new(); 291 292 if(!gtk_builder_add_from_file(gb,filename,NULL)) 293 return NULL; 294 295 gtk_builder_connect_signals(gb,NULL); 296 297 return gb; 298 299 } 300 void cal_widget_init() 301 302 { 303 304 gtk_widget_show(GTK_WIDGET(window1)); 305 306 } 307 308 void cal_get_widgets(GtkBuilder* gb) 309 310 { 311 312 w_(gb,WINDOW,login); 313 314 w_(gb,ENTRY,entry_id); 315 w_(gb,ENTRY,entry_pwd); 316 317 w_(gb,WINDOW,window1); 318 319 w_(gb,TEXT_VIEW,text_view); 320 w_(gb,WIDGET,textview1); 321 w_(gb,ENTRY,name_entry); 322 323 } 324 //登录按钮的响应函数 325 void mysql_connect() 326 { 327 char sql[MAXLINE]; 328 const gchar *entry1; 329 const gchar *entry2; 330 entry1=gtk_entry_get_text(GTK_ENTRY(entry_id)); 331 entry2=gtk_entry_get_text(GTK_ENTRY(entry_pwd)); 332 333 if (strcmp(entry1, "") == 0) { 334 show_info("帐号不能为空!"); 335 return; 336 } 337 if (strcmp(entry2, "") == 0) { 338 show_info("密码不能为空!"); 339 return; 340 } 341 342 sprintf(sql,"select count(*) from users where user=‘%s‘ and passwd=‘%s‘",entry1,entry2); 343 344 rs=exe_sql(sql); 345 346 row=mysql_fetch_row(rs); 347 348 const gchar *a=row[0]; 349 350 if(strcmp(a,"1")==0) 351 { 352 show_info("成功登录!"); 353 if(!g_thread_supported()) 354 g_thread_init(NULL); 355 //初始线程 356 357 GtkBuilder *gb; 358 359 gb=gtk_load_glade("try1.glade"); 360 gtk_widget_destroy(login); 361 if(gb==NULL) 362 return -1; 363 364 cal_get_widgets(gb); 365 366 cal_widget_init(); 367 return 0; 368 } 369 else 370 371 show_info("用户名或密码失败\n"); 372 return; 373 } 374 //创建button按钮 375 GtkWidget *create_button() 376 { 377 GtkWidget *button = gtk_button_new(); 378 return button; 379 } 380 //退出按钮 381 void btn_cal_clicked(GtkWidget *dialog,gpointer data) 382 { 383 gtk_widget_destroy(regwindow); 384 return FALSE; 385 } 386 //注册的响应函数 387 void reg_btn2_clicked() 388 { 389 int rows; 390 MYSQL_ROW *mysql_row; 391 const char *name=gtk_entry_get_text(GTK_ENTRY(reg_entry1)); 392 const char *passwd=gtk_entry_get_text(GTK_ENTRY(reg_entry2)); 393 if (strcmp(name, "") == 0) 394 { 395 show_info("帐号不能为空!"); 396 return; 397 } 398 if (strcmp(passwd, "") == 0) 399 { 400 show_info("密码不能为空!"); 401 return; 402 } 403 char sql[MAXLINE]; 404 char query[MAXLINE]; 405 sprintf(query,"select * from users where user=‘%s‘",name); 406 rs = exe_sql(query); 407 rows=mysql_num_rows(rs); 408 //mysql_row=mysql_fetch_row(rs); 409 //const gchar *b=row[0]; 410 411 if(rows>=1) 412 { 413 show_info("用户名已被注册\n"); 414 return; 415 } 416 else 417 sprintf(sql, "insert into users(user,passwd) values(‘%s‘,‘%s‘)",name,passwd); 418 rs = exe_sql(sql); 419 show_info("注册成功"); 420 } 421 //注册响应函数+注册界面 422 void btn_reg_clicked() 423 { 424 GtkBuilder *gb; 425 GtkWidget *reg_btn1; 426 GtkWidget *reg_btn2; 427 gb=gtk_builder_new(); 428 gtk_builder_add_from_file(gb,"reg.glade",NULL); 429 regwindow=GTK_WIDGET(gtk_builder_get_object(gb,"regwindow")); 430 reg_entry1=GTK_WIDGET(gtk_builder_get_object(gb,"reg_entry1")); 431 reg_entry2=GTK_WIDGET(gtk_builder_get_object(gb,"reg_entry2")); 432 reg_btn1=GTK_WIDGET(gtk_builder_get_object(gb,"reg_btn1")); 433 reg_btn2=GTK_WIDGET(gtk_builder_get_object(gb,"reg_btn2")); 434 update_widget_bg(regwindow, "ico/bg.jpg"); 435 gtk_widget_show(GTK_WIDGET(regwindow)); 436 g_signal_connect(GTK_OBJECT(reg_btn1),"clicked",G_CALLBACK(btn_cal_clicked),regwindow); 437 g_signal_connect(GTK_OBJECT(reg_btn2),"clicked",G_CALLBACK(reg_btn2_clicked),regwindow); 438 } 439 GtkWidget *create_window() //创建窗体和控件!! 440 { 441 gtk_init(NULL, NULL); //初始化 442 GtkBuilder *gb; 443 444 gb=gtk_load_glade("client.glade"); 445 446 cal_get_widgets(gb); 447 update_widget_bg(login, "ico/bg.jpg"); 448 449 gtk_widget_show_all(login); //显示窗体和控件 450 return 0; 451 } 452 int main(int argc,char *argv[]) 453 { 454 455 create_window(); //创建窗体和控件!! 456 gtk_main(); //事件循环处理 457 return 0; 458 }
由于编写时调用了glade界面和mysql数据库,界面和表就不再上传了。
时间: 2024-10-13 16:08:41