嵌入式成长轨迹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编程技术设计实现了一个客户/服务器程序。总的来说,程序还是比较简单、容易理解的。感兴趣的同学还可以在该程序的基础上进行优化,例如将界面加工得更为美观,或添加一些新的功能。

原文地址:https://www.cnblogs.com/zeedmood/p/2457753.html