간단한 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:


댓글 달기