zoukankan      html  css  js  c++  java
  • 基于socket编程的多人聊天室

    效果图:

            

        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
    ",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 "); 62 63 sd = socket(AF_INET,SOCK_STREAM,0); //1.......创建套接子 64   if(sd == -1) 65   { 66    g_print("create socket error! "); 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! "); 78    return -1; 79   } 80   if(listen(sd,8)<0) //3......开启监听 81   { 82 g_print("listen error! "); 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! "); 93    break; 94               } 95     else 96     { 97       if(count >= MAX_USERS) 98       { 99        sprintf(buf,"用户数量过多服务器不能连接。 "); 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
    ",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
    ",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
    ",sd);
    102     if(sd < 0)
    103     { 
    104         gtk_text_buffer_get_end_iter(buffer,&iter);
    105         gtk_text_buffer_insert(buffer,&iter,"打开套接字时出错!
    ",-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,"连接服务器时出错!
    ",-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,"
    成功与服务器连接....
    ",-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
    ",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
    ",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, "
    ", -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("用户名或密码失败
    ");
    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("用户名已被注册
    ");
    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数据库,界面和表就不再上传了。

  • 相关阅读:
    Vue+element UI实现“回到顶部”按钮组件
    JS判断字符串长度的5个方法(区分中文和英文)
    从vue源码看Vue.set()和this.$set()
    mac下git安装与使用
    JS数组reduce()方法详解及高级技巧
    vue中router.go、router.push和router.replace的区别
    上传及更新代码到github(以及如何在vscode上提交自己的代码)
    VSCode打开多个项目文件夹的解决方法
    get请求和post请求的区别
    android 进程的优先级
  • 原文地址:https://www.cnblogs.com/kunpengv5/p/4067557.html
Copyright © 2011-2022 走看看