zoukankan      html  css  js  c++  java
  • 嵌入式成长轨迹25 【Linux应用编程强化】【Linux下的C编程 下】【实例:客户端/服务器端程序】

    给出一个客户/服务器程序开发的案例,实现从服务器状态的远程监视功能。同时,客户端采用图形界面来显示数据。这个案例涵盖了网络编程和GUI编程的相关知识,读者应该注意其中的结合点。具体内容包括:

    服务器端程序设计

    客户端程序设计

     

     

      服务器端程序设计

    服务器端程序的功能是接受客户端的连接,然后提供其状态信息,例如CPU的使用率、内存的分配情况等,这些信息我们通过访问/proc文件系统来获得。

     

      1 /* server.c */
      2 
      3 #include <stdlib.h>
      4 
      5 #include <stdio.h>
      6 
      7 #include <unistd.h>
      8 
      9 #include <errno.h>
     10 
     11 #include <string.h>
     12 
     13 #include <sys/types.h>
     14 
     15 #include <netinet/in.h>
     16 
     17 #include <sys/socket.h>
     18 
     19 #include <arpa/inet.h>
     20 
     21 #define SERV_PORT 2395    /* 服务器监听端口号 */
     22 
     23 #define BACKLOG 10          /* 请求队列的长度数 */
     24 
     25 #define BUF_SIZE 1024              /* 缓冲区的长度 */
     26 
     27 #define MEM_SIZE 32
     28 
     29  
     30 
     31 struct cpustatus
     32 
     33 {
     34 
     35   long total;                       /* 系统从启动到现在的总时间 */
     36 
     37   float user;                        /* 系统从启动到现在用户态的CPU时间(百分比) */
     38 
     39   float nice;                        /* 系统从启动到现在nice值为负的进程所占用的CPU时间(百分比) */
     40 
     41   float system;                    /* 系统从启动到现在核心态的CPU时间(百分比) */
     42 
     43   float idle;                        /* 系统从启动到现在除I/O等待以外的其他等待时间(百分比) */
     44 
     45 };
     46 
     47 struct meminfo
     48 
     49 {
     50 
     51   char total[MEM_SIZE];           /* 系统的总内存空间 */
     52 
     53   char free[MEM_SIZE];           /* 系统的空闲内存空间 */
     54 
     55 };
     56 
     57 void get_cpu_status(struct cpustatus *); /* 获取处理器信息 */
     58 
     59 void get_mem_info(struct meminfo *); /* 获取内存信息 */
     60 
     61  
     62 
     63 int main()
     64 
     65 {
     66 
     67   int ret;
     68 
     69   int pid;                                                 /* 定义进程标识符 */
     70 
     71   int sockfd;                                      /* 定义监听Socket描述符 */
     72 
     73   int clientsfd;                                          /* 定义数据传输Socket描述符 */
     74 
     75   struct sockaddr_in host_addr;           /* 本机IP地址和端口号信息 */
     76 
     77   struct sockaddr_in client_addr;               /* 客户端IP地址和端口号信息 */
     78 
     79   unsigned int addrlen;
     80 
     81   char buf[BUF_SIZE];                            /* 定义缓冲区 */
     82 
     83   struct cpustatus cpu_stat;
     84 
     85   struct meminfo mem_info;
     86 
     87   int cnt;
     88 
     89   int size;
     90 
     91   /* 创建套接字 */
     92 
     93   sockfd = socket(AF_INET, SOCK_STREAM, 0);
     94 
     95   if(sockfd == -1)                                    /* 如果套接字创建失败,输出错误信息并退出 */
     96 
     97   {
     98 
     99     printf("socket error\n");
    100 
    101     exit(1);
    102 
    103   }
    104 
    105   /* 将套接字与IP地址和端口号进行绑定 */
    106 
    107   host_addr.sin_family = AF_INET;                         /* TCP/IP协议 */
    108 
    109   host_addr.sin_port = htons(SERV_PORT);              /* 让系统随机选择一个未被占用的端口号 */
    110 
    111   host_addr.sin_addr.s_addr = INADDR_ANY;          /* 本机IP地址 */
    112 
    113   bzero(&(host_addr.sin_zero), 8);                           /* 清零 */
    114 
    115   ret = bind(sockfd, (struct sockaddr *)&host_addr, sizeof(struct sockaddr));   /* 绑定 */
    116 
    117   if(ret == -1)                                                       /* 如果套接字绑定失败,输出错误信息并退出 */
    118 
    119   {
    120 
    121     printf("bind error\n");
    122 
    123     exit(1);
    124 
    125   }
    126 
    127   /* 将套接字设为监听模式,以等待连接请求 */
    128 
    129   ret = listen(sockfd, BACKLOG);
    130 
    131   if(ret == -1) {
    132 
    133     perror("listen error\n");
    134 
    135     exit(1);
    136 
    137   }
    138 
    139   printf("Waiting for the client connection.\n ");
    140 
    141   /* 循环处理客户端的请求 */
    142 
    143   while(1)
    144 
    145   {
    146 
    147     addrlen = sizeof(struct sockaddr_in);
    148 
    149     clientsfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);             /* 接受一个客户端连接 */
    150 
    151     if(clientsfd == -1)
    152 
    153     {
    154 
    155       perror("accept error\n");
    156 
    157       continue;
    158 
    159     }
    160 
    161     pid = fork();                               /* 创建子进程 */
    162 
    163     if(pid<0)                                          /* 如果进程创建失败,输出错误信息并退出 */
    164 
    165     {
    166 
    167       perror("fork error\n");
    168 
    169       exit(1);
    170 
    171     }
    172 
    173     if(pid==0)                                        /* 子进程,处理客户端的请求*/
    174 
    175     {
    176 
    177       close(sockfd);                                 /* 关闭父进程的套接字 */
    178 
    179       printf("Client IP : %s\n", inet_ntoa(client_addr.sin_addr));            /* 输出客户端IP地址 */
    180 
    181       /* 获取处理器信息 */
    182 
    183       get_cpu_status(&cpu_stat);
    184 
    185       size  = sizeof(struct cpustatus);
    186 
    187       memcpy(buf, &cpu_stat, size);
    188 
    189       /* 获取内存信息 */
    190 
    191       get_mem_info(&mem_info);
    192 
    193       memcpy(buf+size, &mem_info, sizeof(struct meminfo));
    194 
    195       /* 发送数据 */
    196 
    197       cnt = send(clientsfd, buf, BUF_SIZE, 0);
    198 
    199       if(cnt == -1)
    200 
    201       {
    202 
    203         perror("send error\n");
    204 
    205         exit(1);
    206 
    207       }
    208 
    209       printf("Done!\n", buf);                   /* 程序测试使用 */
    210 
    211       close(clientsfd);                       /* 关闭当前客户端连接 */
    212 
    213       exit(0);                                         /* 子进程退出 */
    214 
    215     }
    216 
    217     close(clientsfd);                                  /* 父进程,关闭子进程的套接字,准备接受下一个客户端连接 */
    218 
    219   }
    220 
    221   return 0;
    222 
    223 }
    224 
    225  
    226 
    227 void get_cpu_status(struct cpustatus *cpu_stat)
    228 
    229 {
    230 
    231   long total;
    232 
    233   float user, nice, system, idle;
    234 
    235   long cpu[21];
    236 
    237   char text[201];
    238 
    239   FILE *fp;
    240 
    241   fp = fopen("/proc/stat", "r");                   /* 如果/proc/stat文件 */
    242 
    243   if (fp == NULL)                                   /* 如果文件打开失败,输出错误信息并退出 */
    244 
    245   {
    246 
    247     printf("open stat failed\n");
    248 
    249     exit(1);
    250 
    251   }
    252 
    253   while(fgets(text, 200, fp) != NULL)        /* 提取处理器信息 */
    254 
    255   {
    256 
    257     if(strstr(text, "cpu"))
    258 
    259     {
    260 
    261       sscanf(text, "%s %f %f %f %f", cpu, &user, &nice, &system, &idle);
    262 
    263     }
    264 
    265   }
    266 
    267   fclose(fp);                                     /* 关闭文件 */
    268 
    269   /* 进行各类CPU时间 */
    270 
    271   total = user + nice + system + idle;
    272 
    273   user = (user / total) * 100;
    274 
    275   nice = (nice / total) * 100;
    276 
    277   system = (system / total) * 100;
    278 
    279   idle = (idle / total) * 100;
    280 
    281   /* 对结构体各成员进行赋值 */
    282 
    283   cpu_stat->total = total;
    284 
    285   cpu_stat->user = user;
    286 
    287   cpu_stat->nice = nice;
    288 
    289   cpu_stat->system = system;
    290 
    291   cpu_stat->idle = idle;
    292 
    293   return;
    294 
    295 }
    296 
    297  
    298 
    299 void get_mem_info(struct meminfo *minfo)
    300 
    301 {
    302 
    303   int i, j;
    304 
    305   char total[MEM_SIZE];
    306 
    307   char free[MEM_SIZE];
    308 
    309   char temp[MEM_SIZE*2];
    310 
    311   FILE *fp;
    312 
    313   fp = fopen("/proc/meminfo", "r");           /* 如果/proc/meminfo文件 */
    314 
    315   if (fp == NULL)                                   /* 如果文件打开失败,输出错误信息并退出 */
    316 
    317   {
    318 
    319     printf("open meminfo failed\n");
    320 
    321     exit(1);
    322 
    323   }
    324 
    325   fgets(temp, MEM_SIZE*2, fp);
    326 
    327   strcpy(total, temp);                         /* 系统的总内存空间信息(字符串) */
    328 
    329   fgets(temp, MEM_SIZE*2, fp);
    330 
    331   strcpy(free, temp);                               /* 系统的空闲内存空间信息(字符串) */
    332 
    333   fclose(fp);                                     /* 关闭文件 */
    334 
    335   if(strlen(total) > 0)                         /* 提取总内存空间信息字符串中的数值部分 */
    336 
    337   {
    338 
    339     for(i=0,j=0; i<strlen(total); i++)
    340 
    341     {
    342 
    343       if(isdigit(total[i]))
    344 
    345         minfo->total[j++] = total[i];
    346 
    347     }
    348 
    349     minfo->total[j] = '\0';                         /* 字符串结束符 */
    350 
    351   }
    352 
    353   if(strlen(free) > 0)                                 /* 提取空闲内存空间信息字符串中的数值部分 */
    354 
    355   {
    356 
    357     for(i=0,j=0; i<strlen(free); i++)
    358 
    359     {
    360 
    361       if(isdigit(free[i]))
    362 
    363         minfo->free[j++] = free[i];
    364 
    365     }
    366 
    367     minfo->free[j] = '\0';                          /* 字符串结束符 */
    368 
    369   }
    370 
    371   return;
    372 
    373 }

     

     

      客户端程序设计

    客户端程序我们分两步来实现,首先在字符界面下设计实现,调试通过后,再设计开发图形界面。

     

    1         字符界面客户端程序

    首先开发字符界面下的客户端程序,该程序的功能比较简单,连接服务器,获取其状态信息,并输出到屏幕。

     

      1 /* client.c */
      2 
      3 #include <stdlib.h>
      4 
      5 #include <stdio.h>
      6 
      7 #include <unistd.h>
      8 
      9 #include <errno.h>
     10 
     11 #include <string.h>
     12 
     13 #include <sys/types.h>
     14 
     15 #include <netinet/in.h>
     16 
     17 #include <sys/socket.h>
     18 
     19 #define SERV_PORT 2395                  /* 服务器监听端口号 */
     20 
     21 #define BUF_SIZE 1024                            /* 缓冲区的长度 */
     22 
     23 #define MEM_SIZE 32
     24 
     25  
     26 
     27 struct cpustatus                                   /* 处理器信息 */
     28 
     29 {
     30 
     31   long total;
     32 
     33   float user;
     34 
     35   float nice;
     36 
     37   float system;
     38 
     39   float idle;
     40 
     41 };
     42 
     43 struct meminfo                                          /* 内存信息 */
     44 
     45 {
     46 
     47   char total[MEM_SIZE];
     48 
     49   char free[MEM_SIZE];
     50 
     51 };
     52 
     53  
     54 
     55 int main(int argc, char **argv)
     56 
     57 {
     58 
     59   int ret;
     60 
     61   int sockfd;                                     /* 定义Socket描述符 */
     62 
     63   struct sockaddr_in serv_addr;          /* 服务器IP地址和端口号信息 */
     64 
     65   char buf[BUF_SIZE];                            /* 定义缓冲区 */
     66 
     67   struct cpustatus cpu_stat;
     68 
     69   struct meminfo mem_info;
     70 
     71   int cnt;
     72 
     73   int size;
     74 
     75   if(argc != 2)                                         /* 检查命令行参数个数是否正确 */
     76 
     77   {
     78 
     79     printf("arguments error.\n");
     80 
     81     exit(1);
     82 
     83   }
     84 
     85   /* 创建套接字 */
     86 
     87   sockfd = socket(AF_INET, SOCK_STREAM, 0);
     88 
     89   if(sockfd == -1)                                                  /* 如果套接字创建失败,输出错误信息并退出 */
     90 
     91   {
     92 
     93     printf("socket error\n");
     94 
     95     exit(1);
     96 
     97   }
     98 
     99   /* 向服务器发出连接请求 */
    100 
    101   serv_addr.sin_family = AF_INET;                         /* TCP/IP协议 */
    102 
    103   serv_addr.sin_port = htons(SERV_PORT);             /* 服务器端口号,并转换为网络字节顺序 */
    104 
    105   serv_addr.sin_addr.s_addr = inet_addr(argv[1]);     /* 服务器的IP地址 */
    106 
    107   bzero(&(serv_addr.sin_zero), 8);                          /* 清零 */
    108 
    109   ret = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr));     /* 连接 */
    110 
    111   if(ret == -1)                                                       /* 如果连接失败,输出错误信息并退出 */
    112 
    113   {
    114 
    115     printf("connect error\n");
    116 
    117     exit(1);
    118 
    119   }
    120 
    121   /* 接收数据 */
    122 
    123   cnt = recv(sockfd, buf, BUF_SIZE, 0);
    124 
    125   if(cnt == -1)
    126 
    127   {
    128 
    129     perror("recv error\n");
    130 
    131     exit(1);
    132 
    133   }
    134 
    135   size  = sizeof(struct cpustatus);
    136 
    137   memcpy(&cpu_stat, buf, size);
    138 
    139   memcpy(&mem_info, buf+size, sizeof(struct meminfo));
    140 
    141   /* 输出接收到数据 */
    142 
    143   printf("CPU Information\n");
    144 
    145   printf("------------------------\n");
    146 
    147   printf("user :\t\t %.2f\%\n", cpu_stat.user);
    148 
    149   printf("nice :\t\t %.2f\%\n", cpu_stat.nice);
    150 
    151   printf("system :\t %.2f\%\n", cpu_stat.system);
    152 
    153   printf("idle :\t\t %.2f\%\n", cpu_stat.idle);
    154 
    155   printf("Memory Information\n");
    156 
    157   printf("------------------------\n");
    158 
    159   printf("total :\t\t %s kB\n",mem_info.total);
    160 
    161   printf("free :\t\t %s kB \n",mem_info.free);
    162 
    163   close(sockfd);                                /* 关闭套接字 */
    164 
    165   return 0;
    166 
    167 }

     

     

    2         图形界面客户端程序

    接下来设计开发客户端的图形界面,这里使用Glade来协助完成。

     

     

      1 /*
      2 
      3  * Initial main.c file generated by Glade. Edit as required.
      4 
      5  * Glade will not overwrite this file.
      6 
      7  */
      8 
      9  
     10 
     11 #ifdef HAVE_CONFIG_H
     12 
     13 #  include <config.h>
     14 
     15 #endif
     16 
     17  
     18 
     19 #include <gtk/gtk.h>
     20 
     21  
     22 
     23 #include "interface.h"
     24 
     25 #include "support.h"
     26 
     27  
     28 
     29 GtkWidget *entry1;
     30 
     31 GtkWidget *textview1;
     32 
     33   int
     34 
     35 main (int argc, char *argv[])
     36 
     37 {
     38 
     39   GtkWidget *window1;
     40 
     41  
     42 
     43 #ifdef ENABLE_NLS
     44 
     45   bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
     46 
     47   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
     48 
     49   textdomain (GETTEXT_PACKAGE);
     50 
     51 #endif
     52 
     53  
     54 
     55   gtk_set_locale ();
     56 
     57   gtk_init (&argc, &argv);
     58 
     59  
     60 
     61   add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
     62 
     63  
     64 
     65   /*
     66 
     67    * The following code was added by Glade to create one of each component
     68 
     69    * (except popup menus), just so that you see something after building
     70 
     71    * the project. Delete any components that you don't want shown initially.
     72 
     73    */
     74 
     75   window1 = create_window1 ();
     76 
     77   gtk_widget_show (window1);
     78 
     79  
     80 
     81   gtk_main ();
     82 
     83   return 0;
     84 
     85 }
     86 
     87  
     88 
     89 /*
     90 
     91  * DO NOT EDIT THIS FILE - it is generated by Glade.
     92 
     93  */
     94 
     95  
     96 
     97 #ifdef HAVE_CONFIG_H
     98 
     99 #  include <config.h>
    100 
    101 #endif
    102 
    103  
    104 
    105 #include <sys/types.h>
    106 
    107 #include <sys/stat.h>
    108 
    109 #include <unistd.h>
    110 
    111 #include <string.h>
    112 
    113 #include <stdio.h>
    114 
    115  
    116 
    117 #include <gdk/gdkkeysyms.h>
    118 
    119 #include <gtk/gtk.h>
    120 
    121  
    122 
    123 #include "callbacks.h"
    124 
    125 #include "interface.h"
    126 
    127 #include "support.h"
    128 
    129  
    130 
    131 #define GLADE_HOOKUP_OBJECT(component,widget,name) \
    132 
    133   g_object_set_data_full (G_OBJECT (component), name, \
    134 
    135       gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
    136 
    137  
    138 
    139 #define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \
    140 
    141   g_object_set_data (G_OBJECT (component), name, widget)
    142 
    143  
    144 
    145   GtkWidget*
    146 
    147 create_window1 (void)
    148 
    149 {
    150 
    151   GtkWidget *window1;
    152 
    153   GtkWidget *fixed1;
    154 
    155   GtkWidget *fixed2;
    156 
    157   extern GtkWidget *entry1;
    158 
    159   extern GtkWidget *textview1;
    160 
    161   GtkWidget *label2;
    162 
    163   GtkWidget *label1;
    164 
    165   GtkWidget *button1;
    166 
    167  
    168 
    169   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    170 
    171   gtk_window_set_title (GTK_WINDOW (window1), _("remote monitor"));
    172 
    173  
    174 
    175   fixed1 = gtk_fixed_new ();
    176 
    177   gtk_widget_show (fixed1);
    178 
    179   gtk_container_add (GTK_CONTAINER (window1), fixed1);
    180 
    181   gtk_widget_set_size_request (fixed1, 264, 302);
    182 
    183  
    184 
    185   fixed2 = gtk_fixed_new ();
    186 
    187   gtk_widget_show (fixed2);
    188 
    189   gtk_fixed_put (GTK_FIXED (fixed1), fixed2, 136, 104);
    190 
    191   gtk_widget_set_size_request (fixed2, 50, 50);
    192 
    193  
    194 
    195   entry1 = gtk_entry_new ();
    196 
    197   gtk_widget_show (entry1);
    198 
    199   gtk_fixed_put (GTK_FIXED (fixed1), entry1, 104, 224);
    200 
    201   gtk_widget_set_size_request (entry1, 144, 24);
    202 
    203   gtk_entry_set_invisible_char (GTK_ENTRY (entry1), 8226);
    204 
    205  
    206 
    207   textview1 = gtk_text_view_new ();
    208 
    209   gtk_widget_show (textview1);
    210 
    211   gtk_fixed_put (GTK_FIXED (fixed1), textview1, 16, 42);
    212 
    213   gtk_widget_set_size_request (textview1, 232, 172);
    214 
    215  
    216 
    217   label2 = gtk_label_new (_("Server Information :"));
    218 
    219   gtk_widget_show (label2);
    220 
    221   gtk_fixed_put (GTK_FIXED (fixed1), label2, 10, 16);
    222 
    223   gtk_widget_set_size_request (label2, 160, 24);
    224 
    225  
    226 
    227   label1 = gtk_label_new (_("IP Address:\n"));
    228 
    229   gtk_widget_show (label1);
    230 
    231   gtk_fixed_put (GTK_FIXED (fixed1), label1, 16, 227);
    232 
    233   gtk_widget_set_size_request (label1, 80, 20);
    234 
    235   gtk_label_set_justify (GTK_LABEL (label1), GTK_JUSTIFY_CENTER);
    236 
    237  
    238 
    239   button1 = gtk_button_new_with_mnemonic (_("Update"));
    240 
    241   gtk_widget_show (button1);
    242 
    243   gtk_fixed_put (GTK_FIXED (fixed1), button1, 176, 256);
    244 
    245   gtk_widget_set_size_request (button1, 70, 29);
    246 
    247  
    248 
    249   g_signal_connect ((gpointer) entry1, "activate",
    250 
    251       G_CALLBACK (on_entry1_activate),
    252 
    253       NULL);
    254 
    255   g_signal_connect ((gpointer) button1, "clicked",
    256 
    257       G_CALLBACK (on_button1_clicked),
    258 
    259       NULL);
    260 
    261  
    262 
    263   /* Store pointers to all widgets, for use by lookup_widget(). */
    264 
    265   GLADE_HOOKUP_OBJECT_NO_REF (window1, window1, "window1");
    266 
    267   GLADE_HOOKUP_OBJECT (window1, fixed1, "fixed1");
    268 
    269   GLADE_HOOKUP_OBJECT (window1, fixed2, "fixed2");
    270 
    271   GLADE_HOOKUP_OBJECT (window1, entry1, "entry1");
    272 
    273   GLADE_HOOKUP_OBJECT (window1, textview1, "textview1");
    274 
    275   GLADE_HOOKUP_OBJECT (window1, label2, "label2");
    276 
    277   GLADE_HOOKUP_OBJECT (window1, label1, "label1");
    278 
    279   GLADE_HOOKUP_OBJECT (window1, button1, "button1");
    280 
    281  
    282 
    283   return window1;
    284 
    285 }
    286 
    287  
    288 
    289 #ifdef HAVE_CONFIG_H
    290 
    291 #  include <config.h>
    292 
    293 #endif
    294 
    295  
    296 
    297 #include <gtk/gtk.h>
    298 
    299  
    300 
    301 #include "callbacks.h"
    302 
    303 #include "interface.h"
    304 
    305 #include "support.h"
    306 
    307  
    308 
    309 #include <stdlib.h>
    310 
    311 #include <stdio.h>
    312 
    313 #include <unistd.h>
    314 
    315 #include <errno.h>
    316 
    317 #include <string.h>
    318 
    319 #include <sys/types.h>
    320 
    321 #include <netinet/in.h>
    322 
    323 #include <sys/socket.h>
    324 
    325 #define SERV_PORT 2395                  /* 服务器监听端口号 */
    326 
    327 #define BUF_SIZE 1024                            /* 缓冲区的长度 */
    328 
    329 #define MEM_SIZE 32
    330 
    331  
    332 
    333  
    334 
    335  
    336 
    337 struct cpustatus                                   /* 处理器信息 */
    338 
    339 {
    340 
    341   long total;
    342 
    343   float user;
    344 
    345   float nice;
    346 
    347   float system;
    348 
    349   float idle;
    350 
    351 };
    352 
    353 struct meminfo                                          /* 内存信息 */
    354 
    355 {
    356 
    357   char total[MEM_SIZE];
    358 
    359   char free[MEM_SIZE];
    360 
    361 };
    362 
    363  
    364 
    365  
    366 
    367  
    368 
    369  
    370 
    371   void
    372 
    373 on_button1_clicked                     (GtkButton       *button,
    374 
    375     gpointer         user_data)
    376 
    377 {
    378 
    379  
    380 
    381   int ret;
    382 
    383   int sockfd;                                     /* 定义Socket描述符 */
    384 
    385   struct sockaddr_in serv_addr;          /* 服务器IP地址和端口号信息 */
    386 
    387   char buf[BUF_SIZE];                            /* 定义缓冲区 */
    388 
    389   struct cpustatus cpu_stat;
    390 
    391   struct meminfo mem_info;
    392 
    393   int i, cnt;
    394 
    395   int size;
    396 
    397   char out[6][MEM_SIZE];
    398 
    399   sockfd = socket(AF_INET, SOCK_STREAM, 0);
    400 
    401   if(sockfd == -1)                                                  /* 如果套接字创建失败,输出错误信息并退出 */
    402 
    403   {
    404 
    405     printf("socket error\n");
    406 
    407     exit(1);
    408 
    409   }
    410 
    411  
    412 
    413   extern GtkWidget *entry1;
    414 
    415  
    416 
    417   const gchar *entry_text;
    418 
    419   entry_text = gtk_entry_get_text(entry1);
    420 
    421  
    422 
    423  
    424 
    425   /* 向服务器发出连接请求 */
    426 
    427   serv_addr.sin_family = AF_INET;                         /* TCP/IP协议 */
    428 
    429   serv_addr.sin_port = htons(SERV_PORT);             /* 服务器端口号,并转换为网络字节顺序 */
    430 
    431   serv_addr.sin_addr.s_addr = inet_addr(entry_text);        /* 服务器的IP地址 */
    432 
    433   bzero(&(serv_addr.sin_zero), 8);                          /* 清零 */
    434 
    435   ret = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr));     /* 连接 */
    436 
    437   if(ret == -1)                                                       /* 如果连接失败,输出错误信息并退出 */
    438 
    439   {
    440 
    441     printf("connect error\n");
    442 
    443     exit(1);
    444 
    445   }
    446 
    447   /* 接收数据 */
    448 
    449   cnt = recv(sockfd, buf, BUF_SIZE, 0);
    450 
    451   if(cnt == -1)
    452 
    453   {
    454 
    455     perror("recv error\n");
    456 
    457     exit(1);
    458 
    459   }
    460 
    461   size  = sizeof(struct cpustatus);
    462 
    463   memcpy(&cpu_stat, buf, size);
    464 
    465   memcpy(&mem_info, buf+size, sizeof(struct meminfo));
    466 
    467   /* 输出接收到数据 */
    468 
    469  
    470 
    471   printf("Entry contents : %s\n", entry_text);
    472 
    473   extern GtkWidget *textview1;
    474 
    475   // const gchar *entry_text;
    476 
    477   GtkTextBuffer *buffer;
    478 
    479   buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW (textview1));//取得文本缓冲区 
    480 
    481  
    482 
    483   //PangoFontDescription *fontDesc;
    484 
    485   // fontDesc = pango_font_description_from_string("Courier Pitch Bold 12");
    486 
    487  
    488 
    489   // gtk_widget_modify_font(textview1, fontDesc);
    490 
    491   GtkTextIter start, end;
    492 
    493   //gtk_text_buffer_get_start_iter(buffer,&end); 
    494 
    495   //gtk_text_buffer_get_end_iter(buffer,&end);
    496 
    497   //end = start;
    498 
    499  
    500 
    501   sprintf(out[0],"user :\t\t %.2f\%\n", cpu_stat.user);
    502 
    503   sprintf(out[1],"nice :\t\t %.2f\%\n", cpu_stat.nice);
    504 
    505   sprintf(out[2],"system :\t %.2f\%\n", cpu_stat.system);
    506 
    507   sprintf(out[3],"idle :\t\t %.2f\%\n", cpu_stat.idle);
    508 
    509  
    510 
    511   sprintf(out[4],"total :\t\t %s kB\n",mem_info.total);
    512 
    513   sprintf(out[5],"free :\t\t %s kB \n",mem_info.free);
    514 
    515   gtk_text_buffer_get_start_iter(buffer,&end);   
    516 
    517  
    518 
    519   for(i=5; i>=0; i--)
    520 
    521   {
    522 
    523  
    524 
    525     gtk_text_buffer_get_start_iter(buffer,&end);   
    526 
    527  
    528 
    529     if(i == 3)
    530 
    531     {
    532 
    533       gtk_text_buffer_insert(buffer,&end, "Memory\n-------------------------\n", -1);     
    534 
    535       gtk_text_buffer_get_start_iter(buffer,&end);   
    536 
    537     }
    538 
    539     gtk_text_buffer_insert(buffer,&end, out[i], -1);/*  gtk_text_insert (GTK_TEXT_VIEW(textview1), NULL, &textview1->style->black, NULL, "Supports ", -1);*/
    540 
    541  
    542 
    543   }
    544 
    545   gtk_text_buffer_get_start_iter(buffer,&end);   
    546 
    547   gtk_text_buffer_insert(buffer,&end, "CPU\n-------------------------\n", -1);
    548 
    549   close(sockfd);                                /* 关闭套接字 */
    550 
    551   return 0;
    552 
    553  
    554 
    555  
    556 
    557 }
    558 
    559   void
    560 
    561 on_entry1_activate  (GtkEntry        *entry,    gpointer         user_data)
    562 
    563 {
    564 
    565   const gchar *entry_text;
    566 
    567   entry_text = gtk_entry_get_text(entry);
    568 
    569   printf("Entry contents : %s\n", entry_text);
    570 
    571 }

     

     

     

    小结

    这里基于网络编程和GUI编程技术设计实现了一个客户/服务器程序。总的来说,程序还是比较简单、容易理解的。感兴趣的同学还可以在该程序的基础上进行优化,例如将界面加工得更为美观,或添加一些新的功能。

  • 相关阅读:
    微信小程序wx.chooseImage和wx.previewImage的综合使用(图片上传不限制最多张数)
    js数组与字符串之间的相互转换
    微信小程序wx.previewImage实用案例(交流QQ群:604788754)
    PHP:第一章——PHP中的魔术常量
    小程序模板嵌套以及相关遍历数据绑定
    6 大主流 Web 框架优缺点对比:15篇前端热文回看
    通俗地讲,Netty 能做什么?
    Netty
    为什么选择Netty
    linux下gsoap的初次使用 -- c风格加法实例
  • 原文地址:https://www.cnblogs.com/zeedmood/p/2457753.html
Copyright © 2011-2022 走看看