1 #include "myhead.h"
2 #include "sem.h"
3 #include "socket.h"
4 #include "read_write.h"
5 #include "myhash.h"
6
7 #define ERROR_EXIT(m) (perror(m), exit(-1))
8
9 int listenfd, localfd;
10 int connsockpair[2];
11 int semid;
12 int shmid;
13
14 char sendbuf[1024];
15 char recvbuf[1024];
16 MYSHM *shm;
17 MYSHM connctrl;
18
19 struct sockaddr_in seraddr, cliaddr, localaddr;
20
21 int size = sizeof(seraddr);
//四个哈希表分别存放4对数据
22 HASHNODE *hash_conf[HASH_MAX] = {NULL};//配置文件
23 HASHNODE *hash_pid_ip[HASH_MAX] = {NULL};//客户端进程号与对应的IP地址
24 HASHNODE *hash_ip_count[HASH_MAX] = {NULL};//同一IP的连接数
25 HASHNODE *hash_comm[HASH_MAX] = {NULL};//命令对应的执行函数
26
27
28
29
30 void my_socket()
31 {
32 char ppid[10] = "";
33 char tempip[30] = "";
34 pid_t pid;
35 int msgid;
36 int port = 0;
37 int peripcount = 0;
38 int totalcount = 0;
39 int nowperipcount = 0;
40 struct sigaction myact;
41 struct msgtype msg;
42
43 listenfd = socket(AF_INET,SOCK_STREAM, 0);
44 if(listenfd<0)
45 ERROR_EXIT("socket");
46
47 memset(&seraddr, 0, sizeof(seraddr));
48 seraddr.sin_family = AF_INET;
49 port = atoi((char *)hash_getval(hash_conf,"serverport",1));
50 seraddr.sin_port = htons(port);
51 seraddr.sin_addr.s_addr = inet_addr((char *)hash_getval(hash_conf,"serverip",1));
52
53 /*设置地址重用*/
54 int opt = 1;
55 int res = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, 4);
56 if(res<0)
57 ERROR_EXIT("setsockopt");
58
59 /*绑定侦听套接口*/
60 res = bind(listenfd, (Sockad *)&seraddr, sizeof(seraddr));
61 if(res<0)
62 ERROR_EXIT("bind");
63 /*设置侦听口*/
64 res = listen(listenfd, 5);
65 if(res<0)
66 ERROR_EXIT("listen");
67
68 memset(&myact, 0, sizeof(myact));
69 myact.sa_handler = myquit;
70 sigaction(SIGCHLD, &myact, NULL);
71
72 while(1) {
73 printf("=========wait client connect=========\n");
74
75 memset(&cliaddr, 0, sizeof(cliaddr));
76
77 localfd = accept(listenfd, (Sockad *)&cliaddr, &size);
78 printf("localfd = %d, %d\n", localfd, EINTR);
79 /*accetp()是慢系统调用,在信号产生时会中断accept其调用,
80 使accept返回-1,并将errno变量设置为EINTR,此时应重新调用accept()。*/
81 if(localfd < 0) {
82 if(errno == EINTR)
83 continue;
84 else
85 ERROR_EXIT("accept");
86 }
87
88 /*连接数控制*/
89 totalcount = atoi((char *)hash_getval(hash_conf, "maxip", 1));
90 peripcount = atoi((char *)hash_getval(hash_conf, "perip", 1));
91
92 strcpy(tempip,inet_ntoa(cliaddr.sin_addr));
93 if (NULL == hash_getval(hash_ip_count, tempip, 1))
94 nowperipcount = 0;
95 else
96 nowperipcount = atoi((char *)hash_getval(hash_ip_count, tempip, 1));
97
98 printf("totalcount=%d\n", totalcount);
99 printf("peripcount=%d\n\n", peripcount);
100
101 if (connctrl.conncount >= totalcount || nowperipcount >= peripcount)
102 {
103 write_loop(localfd, "450 connect max\r\n", strlen("450 connect max\r\n"));
104 close(localfd);
105 continue;
106 }
107 else
108 printf("nowperipcount=%d\n\n", nowperipcount+1); //该IP连接数
109
110 memset(&localaddr, 0, sizeof(localaddr));
111 getsockname(localfd, (Sockad *)&localaddr, &size);
112
113 printf("local_addr = %s\n", inet_ntoa(localaddr.sin_addr));
114 printf("local_port = %d\n", ntohs(localaddr.sin_port));
115 printf("client_addr = %s\n", inet_ntoa(cliaddr.sin_addr));
116 printf("client_port = %d\n\n", ntohs(cliaddr.sin_port));
117
118 write_loop(localfd, "220 WELCOM\r\n", strlen("220 WELCOM\r\n"));
119 int pid = fork();
120 switch(pid) {
121 case -1:
122 // close(localfd);
123 // close(listenfd);
124 exit(-1);
125 case(0):
126 close(listenfd);
127 clisession();
128 exit(0);
129 break;
130 default:
131 close(localfd);
132 sprintf(ppid, "%d", pid);
133 printf("ip=[%s] pid=[%s]\n", tempip, ppid);
134 hash_insert(hash_pid_ip, ppid, tempip, 0, NULL);
135 printf("ip=[%s]\n",(char *)hash_getval(hash_pid_ip, ppid, 1));
136 hash_insert(hash_ip_count, tempip, NULL, 1, NULL);
137
138 sem_p(semid);
139 msgid = open_msgqid((key_t)2222);
140 msgrcv(msgid, &msg, sizeof(struct msgtype), 2, 0);
141 msg.exitpid++;
142 msg.mtype = 2;
143 printf("nowtotalcount = %d\n", msg.exitpid);
144 msgsnd(msgid, &msg, sizeof(struct msgtype), 0);
145 sem_v(semid);
146
147 }
148 }
149 }
150
151 void clisession()
152 {
153 char buf[1024] = "";
154 int res, n;
155 res = socketpair(PF_UNIX, SOCK_STREAM, 0, connsockpair);
156 if (-1 == res)
157 ERR_EXIT("socketpair");
158
159 switch (fork())
160 {
161 case -1:
162 ERR_EXIT("datafork");
163 break;
164 case 0:
165 close(connsockpair[0]);
166 while (1)
167 {
168 memset(buf, 0, sizeof(buf));
169 read_line(connsockpair[1], buf, sizeof(buf));
170 exec_com(buf);
171 }
172 break;
173 default :
174 close(connsockpair[1]);
175 while (1)
176 {
177 memset(buf, 0, sizeof(buf));
178 n = read_line(localfd, buf, sizeof(buf));
179 if (0 == n)
180 break;
181 check_com(buf);
182 }
183 }
184 }
185
186 /*执行命令对应函数*/
187 int exec_com(char *buf)
188 {
189 SESSION nowsession;
190 char user[20] = "";
191 char dir[200] = "";
192 char *q = user;
193 FUN p;
194 int i;
195
196
197 memset(&nowsession, 0, sizeof(nowsession));
198 get_com(buf, nowsession.com);
199 get_charm(buf, nowsession.charm);
200 getcwd(nowsession.dir, sizeof(nowsession.dir));
201 if (0 == strncmp(nowsession.com, "LIST", 4))
202 {
203 get_com(nowsession.charm, user);
204 for (i = 0; i < strlen(user); i++)
205 {
206 *(q+i) = tolower(*(q+i));
207 }
208 get_charm(nowsession.charm, dir);
209 strcpy(connuser, user);
210 strcpy(nowsession.dir, dir);
211 }
212 printf("com=[%s]charm=[%s]dir=[%s]\n",
213 nowsession.com, nowsession.charm, nowsession.dir);
214 /* q=(FUN)hash_getval(hash_comm,nowsession.com,2);
215 if(q!=NULL)
216 q(&nowsession);
217 else
218 {
219 write_loop(localfd,REPLY_UNKNOWN_COMM,strlen(REPLY_UNKNOWN_COMM));
220 return -1;
221 } */
222
223 p = (FUN )hash_getval(hash_comm, nowsession.com, 2);
224 if (NULL != p)
225 p(&nowsession);
226 else
227 write_loop(localfd, "500 Unknown command!\r\n", strlen("500 Unknown command!\r\n"));
228 }
229
230 /*检查命令*/
231 int check_com(char *buf)
232 {
233 char temp[1024] = "";
234 char dir[1024] = "";
235 if (0 == strncmp(buf, "LIST", 4)
236 || 0 == strncmp(buf, "PORT", 4)
237 || 0 == strncmp(buf, "PASV", 4)
238 || 0 == strncmp(buf, "REST", 4)
239 || 0 == strncmp(buf, "STOR", 4)
240 || 0 == strncmp(buf, "RETR", 4))
241 {
242 if (0 == strncmp(buf, "LIST", 4))
243 {
244 getcwd(dir, sizeof(dir));
245 sprintf(temp, "%s %s %s\r\n", "LIST", connuser, dir);
246 }
247 else
248 {
249 sprintf(temp, "%s", buf);
250 }
251 write_loop(connsockpair[0], temp, strlen(temp));
252 }
253 else
254 exec_com(buf);
255 }