티스토리 뷰
문제 설명
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