linux套接字编程练习之网络选课模拟

简介:

一.题目:

1 .实验目的

  熟悉和掌握网络编程的基本方法和步骤;

  进一步理解client/server 交互模式;

  加深学生对于网络协议概念的理解以及协议的设计和实现方法

 

2 .实验任务

使用任意网络编程语言( Java 、 C 、 VB 、 Delphi 等)编写网络选课模拟程序,它由 client 和 server 两部分组成, client 和 server 之间的通信基于 TCP 协议,并且实现 NCSP 应用层协议( Network-based Course Selection Protocol )。

 

3 . NCSP 应用层协议

3.1 NCSP Server 的功能

  当接收到 client 发送的 GETCOURSE协议消息,返回该用户已经选择的所有课程名字;

  当接收到 client 发送的 SETCOURSE协议消息,记录用户名和课程名,以便 client 使用 GETCOURSE 命令查询;

  当接收到 client 发送的 SHUTDOWN 协议消息,检查用户是否有此权限,如果有则结束 server 程序。

 

3.2 NCSP Client 的功能

允许用户选择要发送的协议消息及其附带参数,然后向 server 发送 GETCOURSE 、 SETCOURSE 或者 SHUTDOWN 命令之一,并从 server 得到应答结果,显示给用户。

 

3.3 NCSP 协议

本次实验所要实现的网络选课程序,其核心是 client 和 server 之间所遵从的共同协议: NCSP 协议。下面我们详细描述该协议。

 

3.3.1 GETCOURSE

GETCOURSE 命令由 client 发送给 server ,它由一个 ASCII 字符串组成:首先是“GETCOURSE ”,然后紧跟着一个空格( space ),然后是用户名,最后是换行符( '\n' )。 client 然后等待服务器应答:如果返回的是“ 401 User does not exist ”字符串 ,说明该用户还没有选择课程;如果返回的是“200 OK ”字符串,说明该用户已经选择了课程, client 继续接收 server 发送的课程消息,每一门课程名是一个字符串,当接收到“ . ”字符串时,说明课程名发送完毕。 Client 断开连接,重新接收用户输入。

 

当 server 接收到 GETCOURSE 命令,它解析出用户名,然后检索该用户是否已经选择了课程,如果没有,则返回“ 401 User does not exist ”字符串,关闭连接;如果用户选择了课程,则返回“ 200 OK ”字符串,然后将用户选择的课程名返回给 client ,由于用户可能选择了多门课程,因此每一门课程名作为一个字符串返回给 client ,当课程名都发送完毕,发送“ . ”字符串作为结束标志。然后断开连接,重新监听新的 client 的连接请求。

 

当 server 解析 GETCOURSE 命令,发生错误时,返回“ 300 Message format error ”字符串。

 

下面是 client 和 server 的交互:

 

C: GETCOURSE XT

 

S: 200 OK

 

S: Computer Network

 

S: Database Principle

 

S: Java Language

 

S: .

 

3.3.2 SETCOURSE

SETCOURSE 命令由 client 发送给 server ,它由一个 ASCII 字符串组成:首先是“SETCOURSE ”,然后紧跟着一个空格( space ),然后是用户名,最后是换行符( '\n' )。 client 然后等待服务器应答:如果返回的是“ 301 User exists ”字符串,说明该用户已经选择了课程(这里我们假设用户必须一次选择好课程,不能更改);如果返回的是“ 200 OK ”字符串,说明该用户还没有选择课程,可以选课。 Client 将用户输入的课程名发送给 server ,每一门课程名是一个以换行符 '\n' 终结的字符串,当课程名都发送完毕,发送“ . ”字符串作为结束标志。然后 Client 断开连接,重新接收用户输入。

 

当 server 接收到 SETCOURSE 命令,它解析出用户名,然后检索该用户是否已经选择了课程,如果已经选择,则返回“ 301 User exists ”字符串,关闭连接;如果用户还没有选择课程,则返回“ 200 OK ”字符串, server 继续接收 client 发送的课程消息,每一门课程名是一个字符串,当接收到“ . ”字符串时,说明课程名发送完毕。 Server 将用户名和其选择的所有课程存储起来,然后断开连接,重新监听新的 client 的连接请求。

 

当 server 解析 SETCOURSE 命令,发生错误时,返回“ 300 Message format error ”字符串。

 

下面是 client 和 server 的交互:

 

C: SETCOURSE XT

 

S: 200 OK

 

C: Computer Network

 

C: Database Principle

 

C: Java Language

 

C: .

 

3.3.3 SHUTDOWN

SHUTDOWN 命令由 client 发送给 server ,它由一个 ASCII 字符串组成:首先是“SHUTDOWN ”,然后紧跟着一个空格( space ),然后是用户名,最后是换行符( '\n' )。 client 发送完毕后,接收 server 的响应结果,显示在屏幕上,然后关闭连接。

 

当 server 接收到 SHUTDOWN 命令,解析出用户名,如果此用户没有关闭 server 的权限,则返回“ 201 User not allowed to execute this command ”字符串;如果此用户具有关闭 server 的权限,则返回“ 200 OK ”字符串,然后关闭连接,结束 server 程序。

 

当 server 解析 SHUTDOWN 命令,发生错误时,返回“ 300 Message format error ”字符串。

 

下面是 client 和 server 的交互:

 

C: SHUTDOWN XT

 

S: 200 OK

 

4 .编程提示

  可以采用文本或者图形界面(GUI )进行输入和输出;

  协议命令的打包和解析是编制程序要考虑的关键问题之一;

  server 采用什么样的数据结构存储用户及其所选择的课程名也是编制程序要考虑的关键问题之一。为了简化程序,可以规定一个用户最多选择的课程数。

 

5 .实验报告提交内容

  server 源程序和 client 源程序,并且加上必要的注释(以便表明你理解代码的含义)

  实验报告

 

6 .实验成绩评分标准

  正确性 (70%)

  文档和注释 (20%)

  程序风格 (10%)

 




二.整体思路:

在文件中存储用户和课程信息,每一行存储一个用户或课程信息,然后从SETCOURSE命令为切入点,因为要先SET然后才能GET,然后一步一步的添加功能。对于权限问题,我采取的是随机生成一个0或1,然后加到用户名后面,0为特权用户,1为普通用户。



三.注意点:

在成功的运行了第一次之后,再次启动服务器端程序时,./server就会变得邪恶起来,在bind()这个函数中会出现了Address already in use这个错误。当出现这个错误时,我在百度上搜到的资料如下:

下面是IBM官网上对这一情况的具体解释,参见

http://www.ibm.com/developerworks/cn/linux/l-sockpit/

     bind 普遍遭遇的问题是试图绑定一个已经在使用的端口。该陷阱是也许没有活动的套接字存在,但仍然禁止绑定端口(bind 返回 EADDRINUSE),它由 TCP 套接字状态 TIME_WAIT 引起。该状态在套接字关闭后约保留 2 到 4 分钟。在 TIME_WAIT 状态退出之后,套接字被删除,该地址才能被重新绑定而不出问题。

等待 TIME_WAIT 结束可能是令人恼火的一件事,特别是如果您正在开发一个套接字服务器,就需要停止服务器来做一些改动,然后重启。幸运的是,有方法可以避开 TIME_WAIT 状态。可以给套接字应用 SO_REUSEADDR 套接字选项,以便端口可以马上重用。

考虑清单 3 的例子。在绑定地址之前,我以 SO_REUSEADDR 选项调用 setsockopt。为了允许地址重用,我设置整型参数(on)为 1 (不然,可以设为 0 来禁止地址重用)。

即在服务器程序中,在创建一个套接字之后,在绑定本地地址之前,调用下面的函数:

1
2
3
4
5
if  (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse,  sizeof (reuse)) < 0)
        {
                 perror ( "setsockopet" );
                 return  -1;
        }




四.程序运行结果:

wKioL1c70g_SvSLAAACK1kQg8m8804.png


wKiom1c70U3Bl5bNAABEUTMkPWI047.png



wKioL1c70lSy0E8GAAAxb-Wi_ho122.png


wKioL1c70oeiPjxaAABQ_MSnh_I886.png





五.相关代码:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
   /****************************************                                                                                                 
   2     > File Name:server.c
   3     > Author:xiaoxiaohui
   4     > mail:1924224891@qq.com
   5     > Created Time:2016年05月15日 星期日 16时06分03秒
   6 ****************************************/
   7                                                                                                                                           
   8 #include<stdio.h>
   9 #include<stdlib.h>
  10 #include<sys/types.h>
  11 #include<sys/socket.h>
  12 #include<unistd.h>
  13 #include <arpa/inet.h>
  14 #include<netinet/in.h>
  15 #include<fcntl.h>
  16 #include<string.h>
  17 #include<fcntl.h>
  18 #include<pthread.h>
  19 
  20 #define LEN 1024
  21  const  int  PORT = 8080;
  22  int  listenSock, linkSock;
  23  struct  sockaddr_in lockal;
  24  struct  sockaddr_in client;
  25  char  buf[LEN];
  26 pthread_t tid;
  27 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;    //互斥锁  因为buf是全局的,所以只能有一个线程访问buf
  28 
  29 
  30  void  ListenSock()     //建立一个监听套接字
  31 {
  32     listenSock = socket(AF_INET, SOCK_STREAM, 0);    //返回一个文件描述符
  33 
  34     lockal.sin_family = AF_INET;
  35     lockal.sin_addr.s_addr = htonl(INADDR_ANY);     //适合多网卡
  36     lockal.sin_port = htons(PORT);
  37 
  38      int  on = 1;
  39      if ( (setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, &on,  sizeof (on))) < 0)     //容许端口重用
  40     {
  41          perror ( "setsockopt " );  
  42          exit (EXIT_FAILURE);  
  43     }
  44 
  45      if ( bind(listenSock, ( struct  sockaddr*)&lockal,  sizeof (lockal)) < 0)    //绑定本地地址
  46     {
  47          perror ( "bind" );
  48          exit (0);
  49     }
  50 
  51      if ( listen(listenSock, 5) < 0)     //进入监听状态
  52     {
  53          perror ( "listen" );
  54          exit (1);
  55     }
  56 }
  57 
  58  int  LinkSock()            //返回一个已链接套接字
  59 {
  60      int  size =  sizeof (lockal);
  61     linkSock = accept(listenSock, ( struct  sockaddr*)&client, &size);   //创建一个已链接套接字
  62      if (linkSock < 0)
  63     {
  64          perror ( "accept" );
  65          return  -1;
  66     }
  67 
  68      return  linkSock;
  69 }
  70 
  71  int  checkUser( char * ptr)     //判断文件中是否有字符串ptr  有则返回1  无则返回0
  72 {
  73      if (ptr == NULL)
  74     {
  75          printf ( "checkUser parameter is error\n" );
  76          return  -1;
  77     }                                                                                                                                     
  78 
  79      while (*ptr !=  ' '  )
  80     {
  81         ptr++;
  82     }
  83     ptr++;                     //此时ptr指向用户名
  84 
  85      FILE * fp =  fopen ( "message.txt" "r" );
  86      if (fp == NULL)
  87     {
  88          printf ( "fopen is error!\n" );
  89          exit (3);
  90     }
  91      char * message = NULL;
  92      char  buf[LEN];
  93      while ( (message =  fgets (buf, LEN, fp)) != NULL)  
  94     {
  95          if strstr (message, ptr) != NULL)        //判断ptr是否为message的子串
  96         {
  97              fclose (fp);
  98              return  1;
  99         }
100     }
101      fclose (fp);
102      printf ( "there is not exist this user!\n" );
103      return  0;
104 }
105 
106  int  checkMode( char * ptr)    //检查命令格式 如果返回1则代表格式正确 否则格式错误
107 {
108      if (ptr == NULL)
109     {
110          printf ( "checkMode parameter is error\n" );
111          return  -1;
112     }
113                                                                                                                                           
114      int  count = 0;
115      while (*ptr !=  '\0' )    // 判断ptr中有多少个空格字符
116     {
117          if (*ptr ==  ' ' )
118         {
119             count++;
120         }
121         ptr++;
122     }
123      return  count;                                                                                                                         
124 }
125 
126  void  setcourse()
127 {
128      if ( checkMode(buf) == 1)      //如果只存在一个空格符则命令格式匹配
129     {
130          if ( checkUser(buf) == 1)       //用户名存在 说明已经选择了课程
131         {
132              char  message[] =  "301 User exist" ;
133             write(linkSock, message,  strlen (message));
134         }
135          else                      //用户名不存在,说明还没选择课程
136         {
137              FILE * fp =  fopen ( "message.txt" "a" );    //以追加的方式打开文件
138              fputs (buf,fp);                         //把命令和用户名写到文件中
139 
140              int  root = 0;             //   以linux为参考  0表示超级用户 1表示普通用户
141             root =  rand () % 1;        //随机生成0或1
142              if (root == 0)
143             {
144                  fputc ( '0' , fp);
145             }
146              else
147             {
148                  fputc ( '1' , fp);
149             }
150              fputc ( '\n' , fp);                       //一行只写一个内容
151 
152              char  message[] =  "300 OK" ;
153             write(linkSock, message,  strlen (message));
154 
155              while (1)        //把客户端发来的课程写到文件中
156             {
157                  int  ret = 0;
158                  memset (buf,  '\0' , LEN);
159                 ret = read(linkSock, buf, LEN);
160                 buf[ret] =  '\0' ;
161 
162                  fputs (buf, fp);
163                  fputc ( '\n' , fp);
164 
165                  if strcmp (buf,  "." ) == 0)
166                 {
167                      break ;
168                 }
169             }
170 
171              fclose (fp);
172         }
173     }
174      else                //命令格式不匹配
175     {
176          char  message[] =  "300 Message format error" ;
177         write(linkSock, message,  strlen (message));
178     }
179 
180 }
181 
182  void  getcourse()
183 {
184      char * username = buf;
185      while (*username !=  ' ' )
186     {
187         username++;
188     }
189     username++;                  //此时username指向用户名
190 
191      if ( checkMode(buf) == 1)      //如果只存在一个空格符则命令格式匹配
192     {                                                                                                                                     
193          if ( checkUser(buf) == 0)       //用户名不存在 
194         {
195              char  message[] =  "401 User does not exist" ;
196             write(linkSock, message,  strlen (message));
197         }
198          else                      //用户名存在,说明选择了课程
199         {
200              FILE * fp =  fopen ( "message.txt" "r" );    //以读的方式打开文件
201              char  message[] =  "200 OK" ;
202             write(linkSock, message,  strlen (message));
203 
204              char * content = NULL;
205              while ( (content =  fgets (buf, LEN, fp)) != NULL)     //把课程传到客户端
206             {
207                  if strstr (content, username) != NULL)            //如果读到一行中的子字符串与用户名相同,则把接下来的字符串传到客户端
208                 {
209                      memset (buf,  '\0' , LEN);
210                      while ( fgets (buf, LEN, fp) != NULL)       //把接下来的字符串传到客户端
211                     {
212                         write(linkSock, buf,  strlen (buf)); 
213                          if ( strstr (buf,  "." ) == 0)            //如果遇到 . 则代表课程已经传送完
214                         {
215                              memset (buf,  '\0' , LEN);
216                              break ;
217                         }       
218                          memset (buf,  '\0' , LEN);
219                     }
220 
221                      break ;
222                 }
223             }
224         }
225     }
226 }
227 
228  void  ShutDown()
229 {
230      if ( checkMode(buf) == 1)      //如果只存在一个空格符则命令格式匹配
231     {
232          char * message = NULL;                                                                                                             
233          char  buf[LEN];
234          FILE * fp =  fopen ( "message.txt" "r" );
235 
236          char * username = buf;
237          while (*username !=  ' ' )
238         {
239             username++;
240         }
241         username++;                  //此时username指向用户名
242 
243          while ( (message =  fgets (buf, LEN, fp)) != NULL)
244         {
245              if strstr (message, username) != NULL)    //找到有此用户的一行 然后看用户后面的权限
246             {
247                  if strchr (message,  '0' ) != NULL)     //权限为超级权限,则可以关闭服务器
248                 {
249                      fclose (fp);
250                      exit (11);
251                 }
252                  else          
253                 {
254                      break ;
255                 }
256             }
257         }
258 
259          fclose (fp);
260          char  mes[] =  "201 user not allowed to execute this command" ;      //其它情况都是没有权限关闭服务器
261         write(linkSock, mes,  strlen (mes));
262 
263     }
264      else                //命令格式不匹配
265     {
266          char  message[] =  "300 Message format error" ;
267         write(linkSock, message,  strlen (message));
268     }
269 }
270 
271  void  pthread( int  count)
272 {                                                                                                                                         
273  //  pthread_detach(pthread_self());
274  //  while(1)
275     {
276  //      pthread_mutex_lock(&lock);                //加锁  因为buf是一个全局变量,也可以把buf改为局部变量,  然后把buf传给
277                                                    //   相应的函数,这样就可以不用加锁,性能更高,此处就不改了
278      //  int ret = 0;
279      //  ret = read(linkSock, buf, LEN);
280      //  if(ret < 0)
281      //  {
282      //      perror("read");
283      //      continue;
284      //  }
285      //  buf[ret] = '\0';
286      //  printf("%s\n", buf);
287 
288          if ( strstr (buf,  "SETCOURSE" ) != NULL)
289         {
290             setcourse();
291             close(linkSock);          //关闭链接
292  //          break;
293         }
294          else  if ( strstr (buf,  "GETCOURSE" ) != NULL)
295         {
296             getcourse();
297             close(linkSock);          //关闭链接
298  //          break;
299         }
300          else  if ( strstr (buf,  "SHUTDOWN" ) != NULL)
301         {
302             ShutDown();
303             close(linkSock);          //关闭链接
304  //          break;
305         }
306 
307  //      pthread_mutex_unlock(&lock);
308     }
309 
310      printf ( "the %dth of user exit!\n" ,count);
311      return  NULL;
312 }                                                                                                                                         
313 
314  int  main()
315 {
316     ListenSock();       //进入监听状态
317 
318      int  count = 1;      //用户链接数
319      while (1)
320     {
321          if ( LinkSock() >= 0)         //文件描述符从0开始
322         {
323              int  ret = 0;
324             ret = read(linkSock, buf, LEN);
325              if (ret < 0)
326             {
327                  perror ( "read" );
328                  continue ;
329             }
330             buf[ret] =  '\0' ;
331              printf ( "%s\n" , buf);
332             
333  //          int error =  pthread_create(&tid, NULL, pthread, (void*)count);
334  //          if( error != 0 )         //创建线程失败则继续等待链接请求
335  //          {
336  //              printf("pthread_create is error\n");
337  //              continue;             
338  //          }
339 
340             pthread(count);
341             count++;
342 
343  //          if( pthread_join(tid, NULL) == 0)         //等待线程终止         不能用pthread_join因为它是阻塞式的等待
344  //          {                                                               //从而会停在这不会往下继续执行,就满足不了多用户同时存在
345  //              printf("the %dth of user exit!\n");
346  //          }
347         }
348     }
349 
350      return  0;
351 }
352                                                                                                                                           
353 
354 
355

client.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
   /****************************************
   2     > File Name:client.c
   3     > Author:xiaoxiaohui
   4     > mail:1924224891@qq.com
   5     > Created Time:2016年05月15日 星期日 16时48分21秒
   6 ****************************************/
  
  
   9 #include<stdio.h>
  10 #include<stdlib.h>
  11 #include<sys/types.h>
  12 #include<sys/socket.h>
  13 #include<unistd.h>
  14 #include <arpa/inet.h>
  15 #include<netinet/in.h>
  16 #include<fcntl.h>
  17 #include<string.h>
  18 #include<fcntl.h>
  19  const  int  PORT = 8080;
  20  const  int  LEN = 1024;
  21  struct  sockaddr_in server;                                                                                                                
  22  int  clientSock;
  23 
  24 
  25  void  LinkSock()   //创建一个以链接套接字
  26 {
  27     clientSock = socket(AF_INET, SOCK_STREAM, 0);
  28 
  29     server.sin_family = AF_INET;
  30     server.sin_addr.s_addr = inet_addr( "127.0.0.1" );
  31     server.sin_port = htons(PORT);
  32      if ( connect(clientSock, ( struct  sockaddr*)&server,  sizeof (server)) < 0)
  33     {
  34          perror ( "connect" );
  35          exit (0);
  36     }
  37      else
  38     {
  39          printf ( "connect success!   ip:%d  port:%d\n" , server.sin_addr.s_addr, PORT);
  40     }
  41 }
  42 
  43  int  main()
  44 {
  45      printf ( "........................................................\n" );
  46      printf ( "........................................................\n" );
  47      printf ( "...............      you can chose      ................\n" );
  48      printf ( "...............        GETCOURSE        ................\n" );
  49      printf ( "...............        SETCOURSE        ................\n" );
  50      printf ( "...............        SHUTDOWN         ................\n" );
  51      printf ( "........................................................\n" );
  52      printf ( "........................................................\n" );
  53 
  54      char  buf[LEN];
  55 
  56      while (1)
  57     {
  58         LinkSock();      //得到一个已链接套接字
  59 
  60          int  ret = 0;
  61          printf ( "请选择->" );
  62  //      scanf("%[^\n]", &buf);       //%s 不能接受有空格的字符串  或者用gets函数
  63          gets (buf);
  64 
  65         write(clientSock, buf,  strlen (buf));      //把选择的命令发到服务器
  66 
  67          memset (buf,  '\0' , LEN);
  68         ret = read(clientSock, buf, LEN - 1 );    //接受服务器的信息
  69         buf[ret] =  '\0' ;
  70          printf ( "%s" , buf);
  71          printf ( "\n" );
  72 
  73          if ( strstr (buf,  "300 OK" ) != NULL)
  74         {
  75              while (1)
  76             {                                                                                                                             
  77                  printf ( "请输入课程名->" );
  78                  gets (buf);
  79                 write(clientSock, buf,  strlen (buf));
  80                  if ( strcmp (buf,  "." ) == 0)          //如果是 . 则课程发送完毕 退出循环
  81                 {
  82                      break ;
  83                 }
  84 
  85                  memset (buf,  '\0' , LEN);
  86             }
  87 
  88             close(clientSock);
  89              memset (buf,  '\0' , LEN);
  90         }
  91          else  if ( strstr (buf,  "200 OK" ) != NULL)
  92         {
  93              while (1)
  94             {
  95                  memset (buf,  '\0' ,LEN);
  96                 ret = read(clientSock, buf, LEN - 1 );    //接受服务器的信息
  97                 buf[ret] =  '\0' ;
  98                  printf ( "%s" , buf);
  99                  printf ( "\n" );
100                  if ( strstr (buf,  "." ) == 0)    
101                 {
102                      memset (buf,  '\0' , LEN);
103                      break ;
104                 }
105             }
106 
107             close(clientSock);
108         }
109     }
110 
111                                                                                                                                           
112      return  0;
113 }
114

Makefile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1                                                                             
  
   3 .PHONY:all
   4 all:server client
  
   6 server:server.c
   7            gcc -o $@ $^ -g -pthread
   8 client:client.c
   9            gcc -o $@ $^ -g -pthread
  10 
  11 .PHONY:clean
  12 clean:
  13     rm -f server
  14     rm -f client





六.总结:

网络程序出现的问题比较多,一定要通过调试来查出错误的地方,千万不能想着通过看代码看出问题的地方。遇到一个比较复杂的问题时,可以先分割问题,找到切入点,然后一步一步的实现。










本文转自 ye小灰灰  51CTO博客,原文链接:http://blog.51cto.com/10704527/1774540,如需转载请自行联系原作者
目录
相关文章
|
10天前
|
安全 Linux 虚拟化
网络名称空间在Linux虚拟化技术中的位置
网络名称空间(Network Namespaces)是Linux内核特性之一,提供了隔离网络环境的能力,使得每个网络名称空间都拥有独立的网络设备、IP地址、路由表、端口号范围以及iptables规则等。这一特性在Linux虚拟化技术中占据了核心位置🌟,它不仅为构建轻量级虚拟化解决方案(如容器📦)提供了基础支持,也在传统的虚拟机技术中发挥作用,实现资源隔离和网络虚拟化。
网络名称空间在Linux虚拟化技术中的位置
|
10天前
|
网络协议 安全 Linux
Linux网络名称空间之独立网络资源管理
Linux网络名称空间是一种强大的虚拟化技术🛠️,它允许用户创建隔离的网络环境🌐,每个环境拥有独立的网络资源和配置。这项技术对于云计算☁️、容器化应用📦和网络安全🔒等领域至关重要。本文将详细介绍在Linux网络名称空间中可以拥有的独立网络资源,并指出应用开发人员在使用时应注意的重点。
|
10天前
|
安全 网络协议 Linux
Linux网络名称空间概述
Linux网络名称空间是操作系统级别的一种虚拟化技术🔄,它允许创建隔离的网络环境🌐,使得每个环境拥有自己独立的网络资源,如IP地址📍、路由表🗺️、防火墙规则🔥等。这种技术是Linux内核功能的一部分,为不同的用户空间进程提供了一种创建和使用独立网络协议栈的方式。本文旨在全方面、多维度解释Linux网络名称空间的概念、必要性和作用。
Linux网络名称空间概述
|
18天前
|
Linux
Linux中centos桌面消失网络图标
Linux中centos桌面消失网络图标
13 0
|
28天前
|
Shell Linux C语言
【Shell 命令集合 网络通讯 】Linux 向指定用户或终端发送消息 write命令 使用指南
【Shell 命令集合 网络通讯 】Linux 向指定用户或终端发送消息 write命令 使用指南
32 0
|
28天前
|
安全 Unix Shell
【Shell 命令集合 网络通讯 】Linux 向所有当前登录的用户发送消息或通知 wall命令 使用指南
【Shell 命令集合 网络通讯 】Linux 向所有当前登录的用户发送消息或通知 wall命令 使用指南
28 0
|
28天前
|
存储 Shell Linux
【Shell 命令集合 网络通讯 】Linux 显示Unix-to-Unix Copy (UUCP) 系统的状态信息 uustat命令 使用指南
【Shell 命令集合 网络通讯 】Linux 显示Unix-to-Unix Copy (UUCP) 系统的状态信息 uustat命令 使用指南
26 0
|
8天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
24 6
|
10天前
|
网络协议 Linux
在Linux中,管理和配置网络接口
在Linux中管理网络接口涉及多个命令,如`ifconfig`(在新版本中被`ip`取代)、`ip`(用于网络设备配置)、`nmcli`(NetworkManager的CLI工具)、`nmtui`(文本界面配置)、`route/ip route`(处理路由表)、`netstat/ss`(显示网络状态)和`hostnamectl/systemctl`(主机名和服务管理)。这些命令帮助用户启动接口、设置IP地址、查看连接和路由信息。不同发行版可能有差异,建议参考相应文档。
19 4
|
13天前
|
域名解析 监控 网络协议
Linux网卡与IP地址:通往网络世界的通行证 🌐
探索Linux网卡与IP地址关系,理解网卡作为网络通信的关键。Linux网卡需配置IP地址以实现唯一标识、通信、路由、安全管理和网络服务。无IP地址时,网卡在特定情况如局域网服务、网络监控、无线认证和网络启动可有限工作,但通用功能受限。配置IP地址通常通过`ifconfig`(传统)或`ip`(现代)命令,永久配置需编辑网络配置文件。配置错误如IP冲突、子网掩码错误、默认网关和DNS配置不当可能导致服务中断、网络拥堵、安全漏洞和数据丢失。重视网络配置的正确与安全至关重要。
Linux网卡与IP地址:通往网络世界的通行证 🌐