1 /****************************************
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 1 /****************************************
2 > File Name:client.c
3 > Author:xiaoxiaohui
4 > mail:1924224891@qq.com
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
原文地址:http://10704527.blog.51cto.com/10694527/1774540