Engineering/C/C++ Echo Server & Client (using pthread) by 알 수 없는 사용자 2008. 3. 25. /* Echo Server */ #include <stdio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #include <pthread.h> #define BUFSIZE 1024 #define MAXCLIENT 10 /* accept()한 클라이언트를 처리할 쓰레드 함수 */ void* clientHandler(void* arg); /* main() 시작 */ int main(int argc, char* argv[]) { /* 서버와 클라이언트의 소켓을 할당할 변수 */ int serv_sock; int clnt_sock; /* 서버와 클라이언트의 주소정보를 할당할 변수 */ struct sockaddr_in serv_addr; struct sockaddr_in clnt_addr; int clnt_addr_size = sizeof(clnt_addr); /* 쓰레드 id를 저장할 변수*/ pthread_t t_id; /* 사용법 설명 */ if (argc != 2) { fprintf(stderr, "Usage : %s <port>\n", argv[0]); return 0; } /* 소켓 할당 받기 */ if ((serv_sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket() error"); return -1; } /* 구조체 초기화 */ memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(atoi(argv[1])); /* 소켓에 주소 바인딩 */ if (bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) { perror("bind() error"); return -1; } /* 클라이언트 10개까지 접속을 기다림 */ if (listen(serv_sock, MAXCLIENT) == -1) { perror("listen() error"); return -1; } fprintf(stderr,"Waiting for Clients...\n"); /* 무한루프를 돌면서 클라이언트의 접속을 처리함 */ while(1) { /* 클라이언트의 접속을 accept함 */ if ((clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size)) == -1) { perror("accept() error"); return -1; } /* 쓰레드를 하나 생성하여 클라이언트의 소켓을 넘겨줌 */ if (pthread_create(&t_id, NULL, clientHandler, (void*)&clnt_sock) < 0) { perror("pthread_create() error"); return -1; } } close(serv_sock); return 0; } /* accept()한 클라이언트를 처리하는 쓰레드함수 */ void* clientHandler(void* arg) { fprintf(stderr,"A client has been connected\n"); /* 쓰레드를 메인 쓰레드로부터 떼어냄 */ pthread_detach(pthread_self()); /* 메세지를 저장할 버퍼와, 클라이언트의 소켓 번호 */ char buf[BUFSIZE]; int clnt_sock = *((int*)arg); // 형변환 int n_read; /* 클라이언트로부터 메세지를 읽어옴 */ while((n_read = read(clnt_sock, buf, BUFSIZE - 1)) > 0) { write(STDOUT_FILENO, buf, n_read); /* 받은 메세지를 그대로 다시 클라이언트에게 전송 */ if (write(clnt_sock, buf, n_read) < 0) { perror("write() error"); exit(1); } } /* 소켓 닫고, 쓰레드 종료 */ close(clnt_sock); return (void*)NULL; } /* Echo Client */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #define BUFSIZE 1024 /* main() 시작 */ int main(int argc, char* argv[]) { /* 소켓번호, 메세지 길이를 처리할 변수 */ int sock; int str_len, recv_len, recv_num; /* 메세지 버퍼와 서버주소정보를 저장할 변수*/ char message[BUFSIZE]; struct sockaddr_in serv_addr; /* 사용법 설명 */ if (argc != 3) { fprintf(stderr, "Usage : %s <ip> <port>\n", argv[0]); return 0; } /* 소켓 할당받기 */ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { perror("socket() error"); return -1; } /* 서버주소 정보를 담은 구조체 초기화 */ memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(argv[1]); serv_addr.sin_port = htons(atoi(argv[2])); /* 서버에 연결 */ if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { perror("connect() error"); return -1; } fprintf(stderr, "Connected to server(%s : %s)\n", argv[1], argv[2]); /* "q"를 입력받을 때 까지 무한루프를 돌며 서버에 메세지를 보냄 */ while(1) { fprintf(stderr, "Message to Server (q to quit) : "); str_len = read(STDIN_FILENO, message, BUFSIZE - 1); message[str_len] = 0; /* "q" 이면 클라이언트 종료 */ if (!strcmp(message, "q\n")) break; /* 서버에 메세지 전송 */ write(sock, message, str_len); /* 전송했던 메세지를 정확하게 다 받을 때 까지 계속 서버로부터 메세지를 읽어옴 */ for(recv_len = 0; recv_len < str_len ; ) { if ((recv_num = read(sock, message + recv_len, str_len - recv_len)) == -1) perror("read() error"); recv_len += recv_num; } message[str_len] = 0; /* 되돌려 받은 메세지 출력 */ fprintf(stderr, "Message from Server : %s\n", message); } /* 소켓닫고 프로그램 종료 */ close(sock); return 0; } 공유하기 게시글 관리 Humaneer.net 관련글 [펌]변수의 선언과 할당 _t 에 적응해볼까.. -_- 과연 무엇일까? Generic Generate Algorithm