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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux套接字编程练习之网络选课模拟相关的知识,希望对你有一定的参考价值。



  1 /****************************************                                                                                                 
  2     > File Name:server.c
  3     > Author:xiaoxiaohui
  4     > mail:[email protected]
  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



  1 /****************************************
  2     > File Name:client.c
  3     > Author:xiaoxiaohui
  4     > mail:[email protected]
  5     > Created Time:2016年05月15日 星期日 16时48分21秒
  6 ****************************************/
  7 
  8 
  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


本文出自 “水仙花” 博客,请务必保留此出处http://10704527.blog.51cto.com/10694527/1774540

以上是关于linux套接字编程练习之网络选课模拟的主要内容,如果未能解决你的问题,请参考以下文章

集合练习之模拟扑克发牌

python练习之银行模拟系统

网络爬虫练习之网络小说

牛客网编程练习之编程马拉松:发工资

牛客网编程练习之编程马拉松:砌墙

模拟高精度练习之加法