티스토리 뷰
728x90
문제?
서버와 클라어인트 프로그램관 TCP 통신을 한다. 클라이언트는 편의상 fork를 사용하여 5개의 프로세스를 생성하고, 각 클라이언트는 랜덤값을 서버로 전송하고, 처리 결과값을 출력한다. 서버는 각 클라이언트마다 thread를 열고, 클라이언트에서 전송 받은 값을 전역변수인 result에 더한값을 저장하고, 클라이언트에 처리 결과를 넘겨준다. 저장한 값을 순차적으로 처리하기 위해서 mutex를 사용하여 처리한다.
thread에 대한 설명(위키백과)
mutex(상호 배제)에 대한 설명(위키백과)
결과 화면
server 결과 화면
client 결과 화면
소스코드
server code
/* 명령어 : gcc server.c -o server -pthread */ #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> #include <pthread.h> #define MAXLINE 1024 //buf 크기 #define LISTENQ 10 //Listen Q 설정 #define THREAD_NUM 5 //클라이언 동시 접속 수 void *thrfunc(void *arg); //쓰레드 시작 함수 int result = 0; int cntNum = 0; //client count //mutex pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; int main(int argc, char *argv[]) { struct sockaddr_in servaddr, cliaddr; int listen_sock, accp_sock[THREAD_NUM]; int addrlen = sizeof(servaddr); int i, status ; pthread_t tid[THREAD_NUM]; pid_t pid; 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); } while(1) { listen(listen_sock, LISTENQ); puts("client wait...."); accp_sock[cntNum] = accept(listen_sock, (struct sockaddr *)&cliaddr, &addrlen); if(accp_sock[cntNum] < 0) { perror("accept fail"); exit(0); } if((status = pthread_create(&tid[cntNum], NULL, &thrfunc, (void *) &accp_sock[cntNum])) != 0) { printf("%d thread create error: %s\n", cntNum, strerror(status)); exit(0); } //인자로 지정한 스레드 id가 종료하기를 기다립니다. pthread_join(tid[cntNum], NULL); cntNum++; if(cntNum == 5) cntNum = 0; } return 0; } void *thrfunc(void *arg) { int accp_sock = (int) *((int*) arg); int buf; read(accp_sock, &buf, 4); printf("client send value = %d\n", buf); pthread_mutex_lock(&lock); result += buf; printf("result = %d\n", result); pthread_mutex_unlock(&lock); write(accp_sock, &result, 4); close(accp_sock); }
client code
/* 명령어 : gcc client.c -o 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> #include <time.h> #define MAXLINE 1024 //buf 크기 #define TOTALFORK 5 //클라이언트 수 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]; //client fork 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; int strlen = sizeof(servaddr); int sockfd, buf, cNum;//cNum 연결 번호 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); } srand((unsigned)time(NULL)); buf = rand() % 100 + 1; //rand 값 생성 write(sockfd, &buf, 4); //server로 전송 printf("cleint value : %d\n", buf); read(sockfd, &buf, 4); //server에서 받아 옴 printf("Server sum result : %d\n", buf); close(sockfd); }
'Programming language' 카테고리의 다른 글
MFC에서 Chart를 쉽게 그리는 라이브러리 ChartDirector (25) | 2012.06.12 |
---|---|
Google-Blockly으로 미로 찾기 짜보기 (2) | 2012.06.04 |
Python a*x**2 + b*x + c 수식 그래프 그리기 (0) | 2012.05.17 |
MFC ListBox 사용 예제 (0) | 2012.05.15 |
MFC Slider Control 구현하기 (2) | 2012.05.09 |
댓글
Blog is powered by
Tistory / Designed by
Tistory