티스토리 뷰
문제 설명
c언어 TCP 서버와 client 코드입니다. fork()를 이용해서 client는 1개의 부모와 5개의 자식으로 구성되며, 서버는 1개로 구성됩니다. Server로 fork()로 생성된 client 5개가 모두 서버로 접속하고, 접속 정보를 struct(구조체)에 저장하고, 구조체를 각 client로 전송 후 출력하는 코드입니다.
server 결과 화면 및 코드
각 client 접속 로그를 보여주고 있습니다.
Server 코드
/* client 접속 정보를 담기위해서 client_info 구조체 생성 Client 5개가 접속 될 때까지 대기 및 각 클라이언트간 메시지 전송 접속이 완료되면 client_info를 각 클라이언트로 모두 전송 받음 전송 받은 client 정보를 출력 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <unistd.h> #define MAXLINE 1024 //buf 크기 #define LISTENQ 100 //Listen Q 설정 #define TOTALCL 5 //클라이언 동시 접속 수 //client 정보를 저장하기 위한 구조체 (접속 IP, port) struct client_info { char clientAddr[32]; int clientPort; }; int main(int argc, char *argv[]) { struct sockaddr_in servaddr, cliaddr; struct client_info cliinfo[TOTALCL]; int listen_sock, accp_sock[TOTALCL]; int addrlen = sizeof(servaddr); int nbyte; //전송 받은 메시지 byte 저장 char buf[MAXLINE]; int conNum = 0; if(argc != 2) { printf("Use %s PortNumber\n", argv[0]); exit(0); } if((listen_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { perror("socket Fail"); exit(0); } memset(&servaddr, 0, sizeof(servaddr)); //0으로 초기화 servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(atoi(argv[1])); //bind 호출 if(bind(listen_sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("bind Fail"); exit(0); } //소켓을 수동 대기모드로 세팅 listen(listen_sock, LISTENQ); //interative 에코 서비스 수행 while(conNum < 5) { puts("서버가 연결 요청을 대기"); accp_sock[conNum] = accept(listen_sock, (struct sockaddr *)&cliaddr, &addrlen); if(accp_sock[conNum] < 0) { perror("accept fail"); exit(0); } strcpy(cliinfo[conNum].clientAddr, inet_ntoa(cliaddr.sin_addr)); cliinfo[conNum].clientPort = ntohs(cliaddr.sin_port); printf("Client 연결 됨 IP %s, Port %d\n", cliinfo[conNum].clientAddr, cliinfo[conNum].clientPort); //접속 성공 메시지 if((nbyte = read(accp_sock[conNum], buf, MAXLINE)) < 0) { perror("read fail"); exit(0); } buf[nbyte] = 0; if(!strncmp(buf, "Connect Success", 15)) { printf("client message : %s\n", buf); } conNum++; //접속자 수 증가 } puts("모든 클라이언트에 접속 정보 전송"); conNum = 0; while(1) { buf[0] = '\0'; send(accp_sock[conNum], &cliinfo, sizeof(struct client_info) * 5, 0); if((nbyte = read(accp_sock[conNum], buf, MAXLINE)) < 0) { perror("set read fail"); exit(0); } buf[nbyte] = 0; printf("%s\n", buf); if(!strncmp(buf, "GetOK", 5)) { conNum++; if(conNum == 5) break; } } close(listen_sock); return 0; }
Client 실행 및 로그
Client 에서 Server로 접속하고, 모든 client 접속 정보를 출력한 결과화면 입니다.
5개의 자식 프로세스가 동시에 보이고 있기 때문에 pid로 구분하여 출력했습니다.
client 접속 코드
/* fork()를 이용하여 1개의 부모와 5개의 자식 프로세스를 생성 생성된 자식 프로세스는 각각 서버와 connect connect 된 후 서버에 전송해주는 5개의 자식프로세스 접속 정보를 객체로 받아 출력 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <unistd.h> #define MAXLINE 1024 //buf 크기 #define TOTALFORK 5 //클라이언트 수 struct client_info { char clientAddr[32]; int clientPort; }; void createClient(char *port, char *serverIP); int main(int argc, char *argv[]) { if(argc != 3) { printf("Use %s ip_addr port\n", argv[0]); exit(0); } pid_t pids[TOTALFORK]; int runProcess = 0; while(runProcess < TOTALFORK) { sleep(1); pids[runProcess] = fork(); if(pids[runProcess] < 0) { return -1; } if(pids[runProcess] == 0) { createClient(argv[2], argv[1]); exit(0); } else { //부모 프로세스 printf("parent %ld, child %ld\n", (long)getpid(), (long)pids[runProcess]); } runProcess++; } return 0; } void createClient(char *port, char *serverIP) { struct sockaddr_in servaddr; struct client_info *cliinfo; int strlen = sizeof(servaddr); cliinfo = malloc(TOTALFORK); int sockfd, nbyte, cNum;//cNum 연결 번호 char buf[MAXLINE]; if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { perror("socket fail"); exit(0); } memset(&servaddr, 0, strlen); servaddr.sin_family = AF_INET; inet_pton(AF_INET, serverIP, &servaddr.sin_addr); servaddr.sin_port = htons(atoi(port)); if(connect(sockfd, (struct sockaddr *)&servaddr, strlen) < 0) { perror("connect fail"); exit(0); } //접속 성공 메시지 strcpy(buf, "Connect Success"); write(sockfd, buf, sizeof(buf)); //모든 client 접속 정보 받아 옴 recv(sockfd, cliinfo, sizeof(struct client_info) * 5, 0); strcpy(buf, "GetOK"); write(sockfd, buf, sizeof(buf)); printf("pid : %ld, 받은 정보 출력\n", (long)getpid()); int i; for(i = 0; i < TOTALFORK; i++) { printf("pid:%ld, ip:%s port:%d\n", (long)getpid(), cliinfo[i].clientAddr, cliinfo[i].clientPort); } close(sockfd); }
'Programming language' 카테고리의 다른 글
MFC ListBox 사용 예제 (0) | 2012.05.15 |
---|---|
MFC Slider Control 구현하기 (2) | 2012.05.09 |
프로세스 생성 함수 fork() 사용 예제 (6) | 2012.05.03 |
C언어 서버와 클라이언트 간의 UDP 통신 프로그램 코드 (5) | 2012.05.02 |
MFC 달력 컨트롤 사용한 예제 (9) | 2012.05.01 |
댓글
Blog is powered by
Tistory / Designed by
Tistory