给出一个客户/服务器程序开发的案例,实现从服务器状态的远程监视功能。同时,客户端采用图形界面来显示数据。这个案例涵盖了网络编程和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/archive/2012/04/19/2457753.html

嵌入式成长轨迹25 【Linux应用编程强化】【Linux下的C编程 下】【实例:客户端/服务器端程序】...相关推荐

  1. 嵌入式成长轨迹27 【Linux应用编程强化】【中嵌第二阶段】【进程管理】

    补充 成长轨迹19 进程操作 成长轨迹21 多线程编程 中的一些概念 不同之处:进程概念.进程基本状态(这里是最起码的状态).信号量机制 一 进程的基本概念 1  程序的顺序执行和并发执行 1).程序 ...

  2. 嵌入式成长轨迹23 【Linux应用编程强化】【Linux下的C编程 下】【Linux GUI编程】...

    一   GTK+/Gnome开发简介 GTK+是一个用于创建图形用户界面(GUI)的图形库,它在功能上类似微软的MFC,为应用程序提供了一套与平台无关的图形用户接口.GTK+最初用于开发GIMP(Ge ...

  3. 嵌入式成长轨迹11 【嵌入式环境及基础】【Linux shell深入】【深入讨论】

    一.深入讨论awk 1.条件操作符 < >= <= == != 等符号在awk中都存在 ~ 匹配正则表达式 !~不匹配正则表达式 2.逻辑操作符 && || ! 也都 ...

  4. 嵌入式成长轨迹34 【嵌入式学习阶段】【ARM环境调试】【QT 移植环境及简单程序示例】---补充《ok6410 Qt移植百科全书》...

    更新版 http://www.cnblogs.com/zeedmood/archive/2012/12/08/2808393.html 书上提及的有这些,分别说明下,里边打*可以不弄:   Tslib ...

  5. 嵌入式成长轨迹33 【嵌入式学习阶段】【ARM环境调试】【在虚拟机下Ubuntu建立NFS网络文件系统】...

    更新版 http://www.cnblogs.com/zeedmood/archive/2012/12/08/2808376.html (以防参考资料链接无效,将所有参考文章都附后了,所以非常长;实际 ...

  6. 嵌入式成长轨迹61 【智能家居项目】【ARM 飞凌ok6410】【在虚拟机Ubuntu下NFS网络文件系统建立】...

    推荐阅读顺序: 基本环境搭建: [配置]在虚拟机Ubuntu下NFS网络文件系统建立 <ok6410 Qt移植百科全书> [配置]QT&QWT&sqlite3安装配置 这中 ...

  7. 嵌入式成长轨迹54 【Zigbee项目】【CC2430基础实验】【系统睡眠工作状态】

    本实验在小灯闪烁10 次以后进入低功耗模式 PM3 .CC2430 一共有4 种功耗模式,分别是PM0,PM1,PM2,PM3,以 PM3 功耗最低. SLEEP (0xBE) - Sleep mod ...

  8. 嵌入式成长轨迹53 【Zigbee项目】【CC2430基础实验】【串口时钟PC显示】

    void InitT1(void) : 函数原型: 1 void InitT1(void) 2 { 3 T1CCTL0 = 0X44; 4 //T1CCTL0 (0xE5) 5 //T1 ch0 中断 ...

  9. 嵌入式成长轨迹37 【Zigbee项目】【CC2430基础实验】【自动闪烁】

    最为简单的代码,只用到一个寄存器P1DIR.因为点亮的led灯(p1.0和p1.1)的管脚是p1的,要输出就得将这两个管脚设置为输出管脚.该寄存器用0~8对应1.0~1.8管脚. 1 //main.c ...

最新文章

  1. Commonly Hacked Ports
  2. 2017-9-11-颜色空间
  3. insert批量插入500ms_如何快速安全的插入千万条数据
  4. buu [GXYCTF2019]CheckIn
  5. 【热点】因这个配置错误导致全球互联网流量下降了 3.5%
  6. 操作 神通数据库_国产数据库最好的时代
  7. Spring源码:AOP(1)
  8. java 线性回归算法_线性搜索或顺序搜索算法在Java中如何工作? 示例教程
  9. r 保留之前曲线_生存曲线居然能够批量绘制了
  10. [转]MySQL索引背后的数据结构及算法原理
  11. ARM中R0-R15寄存器的作用
  12. console.log的问题
  13. 苹果手机怎样软件签名?
  14. 增广拉格朗日函数的三种统一公式
  15. tfp.distributions.Multinomial().sample()用法简介
  16. c++闭区间内的素数
  17. picker使用以及注意事项
  18. Auto CAD中“旋转”命令怎么使用?
  19. OpenCV实现简单的录屏功能
  20. git -- git emoji列表(github commit 前面的小icon)

热门文章

  1. c语言内存分配与释放 不同类别变量的内存分配和释放的区别
  2. php的控制器,php-模块与控制器
  3. 全球计算机用户人数,NIC2019年11月:全球IPv6 用户数占比中国居43位
  4. Java 只读集合
  5. 恒驰机器人_2545台机器人,1分钟造1辆车,恒大许家印的智能造车工厂首次曝光...
  6. html序列符号替换,Html标签替换(过滤掉html特殊符号)
  7. 中软python编码规范考试试题_卓越分享 | 如何写出一手漂亮的Python代码?
  8. C/C++混淆点-与
  9. opencv22-直方图均衡化
  10. html img src