ftp_socket模型
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 }