간단한 ftp 서버 클라이언트 작성 중 질문입니다.
글쓴이: sm106 / 작성시간: 화, 2011/06/14 - 2:30오후
소스코드입니다.
//server #include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <signal.h> #include <sys/socket.h> #include <sys/file.h> #include <netinet/in.h> #include <string.h> #define MAXLINE 512 #define MAX_SOCK 64 #define TRUE 1 char *escapechar = "bye"; int getmax(int); void removeClient(int); int getDottedIP(int sd, struct sockaddr_in *addr); /* * 새로운 시그널 처리 함수 선언 */ void my_signal(int signo); int maxfdp1; int num_chat = 0; int s; int client_s[MAX_SOCK],client_depth[MAX_SOCK]; FILE *lfp[MAX_SOCK]; /***************************************************************************** 함 수 명 : main 파라메터 : 리 턴 값 : 작 성 일 : 최종변경일 : 설 명 : 서버 포트는 4001번으로 bind 한다. ******************************************************************************/ int main(int argc, char *argv[]) { char rline[MAXLINE+1]; char *start_echo = "Connected to chat-server\n" ">> ftp id:"; char *password_echo = "Connected to chat-server\n" ">> ftp password:"; char *command_echo = "Connected to chat-server\n" ">> ftp command:"; char *filename_echo = "Connected to chat-server\n" ">> ftp filename:"; int i, j, n; int client_fd, clilen; fd_set read_fds; /* 일기 감지할 소켓번호 구조체 */ struct sockaddr_in client_addr, server_addr; /* 초기소켓 생성 */ if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { printf("Server: Can't open stream socket."); exit(0); } /* server_addr 구조체의 내용 세팅 */ bzero((char *)&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(atoi("4001")); if (bind(s, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { printf("Server: Can't bind local address.\n"); exit(0); } if (signal(SIGINT, my_signal) == SIG_ERR) { /* Ctrl+C */ printf("Server: signal(SIGINT) error\n"); exit(0); } if (signal(SIGTERM, my_signal) == SIG_ERR) { /* software termination */ printf("Server: signal(SIGTERM) error\n"); exit(0); } if (signal(SIGQUIT, my_signal) == SIG_ERR) { /* Ctrl+\ */ printf("Server: signal(SIGQUIT) error\n"); exit(0); } /* 클라이언트로부터 연결요청을 기다림 */ listen(s, 5); /* backlog = 5 */ maxfdp1 = s + 1; /* 최대 소켓번호+1 */ while (1) { FD_ZERO(&read_fds); FD_SET(s, &read_fds); for (i=0; i < num_chat; i++) { FD_SET(client_s[i], &read_fds); } maxfdp1 = getmax(s) + 1; /* maxfdp1 재 계산 */ if (select(maxfdp1, &read_fds, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0) { printf("Server: select error <= 0\n"); break; } if (FD_ISSET(s, &read_fds)) { clilen = sizeof(client_addr); client_fd = accept(s, (struct sockaddr *)&client_addr, &clilen); if (client_fd == -1) { printf("Server: accept error\n"); break; } /* 채팅 클라이언트 목록에 추가 */ client_s[num_chat] = client_fd; client_depth[num_chat]=100; num_chat++; send(client_fd, start_echo, strlen(start_echo), 0); if (getDottedIP(client_fd, &client_addr) > -1) printf("%d session(ip: %s)\n", num_chat, inet_ntoa(client_addr.sin_addr)); else printf("%d session\n", num_chat); } /* 클라이언트가 보낸 메시지를 모든 클라이언트게 방송 */ for (i=0; i < num_chat; i++) { if (FD_ISSET(client_s[i], &read_fds)) { if ((n = recv(client_s[i], rline, MAXLINE, 0)) <= 0) { /* 비 정상 종료도 검사가 됨 */ removeClient(i); /* abrupt exit */ continue; } rline[n] = '\0'; /* 종료문자 처리 */ if (strstr(rline, escapechar) != NULL) { removeClient(i); /* abrupt exit */ continue; } if(client_depth[i]==100) { send(client_fd, password_echo, strlen(password_echo), 0); client_depth[i]=200; } else if(client_depth[i]==200) { send(client_fd, command_echo, strlen(command_echo), 0); client_depth[i]=300; } else if(client_depth[i]==300) { send(client_fd, filename_echo, strlen(filename_echo), 0); client_depth[i]=400; } else if(client_depth[i]==400) /* get 일경우 */ { if((lfp[i]=fopen(rline,"w"))==NULL) { removeClient(i); /* abrupt exit */ continue; } client_depth[i]=500; } else if(client_depth[i]==500) { fwrite(rline,1,n,lfp[i]); if(lfp[i] != NULL) fclose(lfp[i]); } } } } /* while */ my_signal(SIGIO); } /***************************************************************************** 함 수 명 : removeClient 파라메터 : 리 턴 값 : 작 성 일 : 최종변경일 : 설 명 : ******************************************************************************/ void removeClient(int i) { struct sockaddr_in client_addr; if (getDottedIP(client_s[i], &client_addr) > -1) printf("@@FTP SESSION DELETE.(IP: %s).\n", inet_ntoa(client_addr.sin_addr)); else printf("@@FTP SESSION DELETE.\n"); close(client_s[i]); if (i != num_chat-1) { client_s[i] = client_s[num_chat-1]; } num_chat--; printf("@@NOW FTP SESSION COUNT = [%d]\n", num_chat); } /***************************************************************************** 함 수 명 : removeClient 파라메터 : 리 턴 값 : 작 성 일 : 최종변경일 : 설 명 : client_s[] 내의 최대 소켓번호 얻기(초기치는 k) ******************************************************************************/ int getmax(int k) { int max = k; int r; for (r=0; r < num_chat; r++) if (client_s[r] > max) max = client_s[r]; return max; } /***************************************************************************** 함 수 명 : removeClient 파라메터 : 리 턴 값 : 작 성 일 : 최종변경일 : 설 명 : 소켓에 연결된 상대방 주소를 알아낸다 ******************************************************************************/ int getDottedIP(int sd, struct sockaddr_in *addr) { struct sockaddr_in client_addr; int len, r; len = sizeof(client_addr); if ((r = getpeername(sd, (struct sockaddr *)&client_addr, &len)) == 0) *addr = client_addr; return r; } /***************************************************************************** 함 수 명 : removeClient 파라메터 : 리 턴 값 : 작 성 일 : 최종변경일 : 설 명 : 시그널 처리 함수 정의 대부분의 시그널(SIGILL과 SIGTRAP 은 제외)에 대한 처리 함수는 시그널이 포작된 후 즉시 재지정된다. 이것은 프로세스가 시그널의 처리 함수를 잊어버리고, 다음에 시그널이 도착하면 묵시적 처리함수인 SIG_DFL 을 수행하는 것을 의미한다. 이것은 특히 사용자가 인터럽트키를 여러번 누를 수도 있는 대화명 프로그램에서 문제가 된다 그러므로 시그널 함수가 호출되자 마자 SIGINT 시그널을 무시한다 ******************************************************************************/ void my_signal(int signo) { int i; signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGQUIT, SIG_IGN); /* 모든 열려있는 소켓을 닫는다 */ close(s); for (i=0; i < num_chat; i++) close(client_s[i]); exit(0); } //client #include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/time.h> #include <string.h> #define MAXLINE 512 #define MAX_SOCK 128 #define TRUE 1 char *escapechar = "bye"; /***************************************************************************** 함 수 명 : main 파라메터 : 리 턴 값 : 작 성 일 : 최종변경일 : 설 명 : ******************************************************************************/ int main(int argc, char *argv[]) { char line[MAXLINE], message[MAXLINE+1]; struct sockaddr_in server_addr; int maxfdp1; int s, k; fd_set read_fds; FILE *lfp=NULL; /* 소켓 생성 */ if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { printf("Client: Can't open stream socket.\n"); exit(0); } /* 채팅 서버의 소켓주소 구조체 server_addr 초기화 */ bzero((char *)&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); server_addr.sin_port = htons(atoi("4001")); /* 연결요청 */ if (connect(s, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { printf("Client: Can't connect to server.\n"); exit(0); } maxfdp1 = s + 1; FD_ZERO(&read_fds); while (1) { FD_SET(0, &read_fds); FD_SET(s, &read_fds); if (select(maxfdp1, &read_fds, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0) { printf("Client: select error\n"); break; } if (FD_ISSET(s, &read_fds)) { int size; if ((size = recv(s, message, MAXLINE, 0)) <= 0) break; /*-- if (message[size-1] != '\n') message[size++] = '\n'; --*/ message[size] = '\0'; printf("%s", message); } if (FD_ISSET(0, &read_fds)) { if(strstr(message,"filename") != NULL) { if (fgets(message, MAXLINE, stdin)) { k=0; for(;;) { if(message[k]==0x00) { message[k-1]=0x00; break; } k++; } sprintf(line,"%s",message); if (send(s, line, strlen(line), 0) < 0) { printf("Client: Write error on socket.\n"); break; } if (strstr(message, escapechar) != NULL) { printf("Good by client.\n"); break; } } if((lfp=fopen(message,"rt"))==NULL) exit(0); fgets(line,sizeof(line),lfp); if (send(s, line, strlen(line), 0) < 0) { printf("Client: Write error on socket.\n"); break; } if(lfp != NULL) fclose(lfp); } else { if (fgets(message, MAXLINE, stdin)) { k=0; for(;;) { if(message[k]==0x00) { message[k-1]=0x00; break; } k++; } sprintf(line,"%s",message); if (send(s, line, strlen(line), 0) < 0) { printf("Client: Write error on socket.\n"); break; } if (strstr(message, escapechar) != NULL) { printf("Good by client.\n"); break; } } } } } close(s); return TRUE; }
get이나 put 명령어 입력시 세션이 종료되어 버리는데 원인을 모르겠습니다.
도와주시겠어요??
Forums:
댓글 달기