2011년7월21일_Talk Server & Client TCP소켓통신과 부모프로세스와 자식프로세스간 PIPE 연결(IPC)
여러가지 방법을 시도하고 있고 조금 더 시간을 투자하면 결과를 낼 수 있으니 기다리삼.
마지막 동기제어신호를 서로간 전송하는 방법을 시도하고 있음.
● Server
1: // talk_server_pipe.c
2: // TCP 1:1 채텅프로그램
3: // 프로세스가 올바르게 종료될 수 있도록 부모/자식 프로세스간
4: // 파이프를 연결하여 종료메시지를 건네준다.
5: // 특징: 서버와 클라이언트간 메시지가 아닌 동기제어신호를 전송함.
6: // read()가 블록이 되지 않으므로 두 가지 장치로 부터 수신가능.
7: //
8: // 작성자: 김수만
9: // 작성일자: 2011년 7월 21일
10: #include <stdio.h>
11: #include <string.h>
12: #include <stdlib.h>
13: #include <sys/types.h>
14: #include <signal.h>
15: #include <sys/socket.h>
16: #include <sys/wait.h>
17: #include <netinet/in.h>
18: #include <arpa/inet.h>
19: #include <unistd.h>
20: #include <signal.h>
21:
22: #define MAXLINE 512
23: #define SYNC 1
24:
25: char *escapechar = "exit"; //종료문자열
26: int server_sock;
27: int client_sock;
28: int fd[2]; //파이프
29:
30: void timer(int); //알람 시그널 처리함수
31:
32: int main(int argc, char *argv[])
33: {
34: int clntlen;
35: int num;
36: char sendline[MAXLINE];
37: char buffer[MAXLINE];
38: char recvline[MAXLINE + 1];
39: int size;
40: pid_t fork_ret;
41: struct sockaddr_in client_addr;
42: struct sockaddr_in server_addr;
43: // signal사용하기 위해 추가된 변수들
44: int state;
45: struct sigaction act;
46:
47: if(argc != 2)
48: {
49: printf("Usage : %s PORT \n", argv[0]);
50: exit(0);
51: }
52:
53: // pipe생성
54: state = pipe(fd);
55: if(-1 == state)
56: {
57: fprintf(stderr, "pipe() error. \n");
58: exit(1);
59: }
60:
61: // signal설정
62: act.sa_handler = timer;
63: sigemptyset(&act.sa_mask);
64: act.sa_flags = 0;
65:
66: //타이머 이벤트사용
67: if(SIG_ERR == sigaction(SIGALRM, &act, 0))
68: {
69: fprintf(stderr, "sigaction() error. \n");
70: exit(1);
71: }
72:
73: // 소켓 생성
74: if((server_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
75: {
76: printf("Server: can't open stream socket. \n");
77: exit(0);
78: }
79:
80: // 소켓주소 구조체에 주소 세팅
81: bzero((char *)&server_addr, sizeof(server_addr)); //소켓주소 구조체 초기화
82: server_addr.sin_family = AF_INET;
83: server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
84: server_addr.sin_port = htons(atoi(argv[1]));
85:
86: // 소켓에 서버 주소 연결
87: if(bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
88: {
89: printf("Server: can't bind local address. \n");
90: exit(0);
91: }
92:
93: printf("Server started. \nWaiting for client..\n");
94: listen(server_sock, 1);
95:
96: // 클라이언트의 연결요청 수락
97: clntlen = sizeof(client_addr);
98: if((client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &clntlen)) < 0)
99: {
100: printf("Server: failed in acceptiong. \n");
101: exit(0);
102: }
103:
104: alarm(1); //1초 후에 알람시그널 발생
105: sleep(1);
106: fork_ret = fork();
107:
108: if(0 < fork_ret)
109: {
110: // 부모 프로세스는 키보드 입력을 클라이언트로 송신
111: while(fgets(sendline, MAXLINE, stdin) != NULL)
112: {
113: strcpy(buffer, "수만 : ");
114: strcat(buffer, sendline);
115: size = strlen(buffer);
116: if(write(client_sock, buffer, strlen(buffer)) != size)
117: {
118: printf("Error in write. \n");
119: }
120:
121: if(strstr(sendline, escapechar) != NULL) //종료문자열 입력시 처리
122: {
123: printf("Good bye. \n");
124: close(client_sock);
125: sleep(3); //3초 후 종료
126: waitpid(-1, &state, WNOHANG); // wait()를 쓰면 더 좋음.
127: break;
128: }
129: }
130: }
131: else if(0 == fork_ret)
132: {
133: // 자식 프로세스는 클라이언트로부터 수신된 메시지를 화면에 출력
134: while(1)
135: {
136: // 클라이언트 -> 서버
137: if((size = read(client_sock, recvline, MAXLINE)) < 0)
138: {
139: printf("Error if read. \n");
140: close(client_sock);
141: exit(0);
142: }
143:
144: recvline[size] = '\0';
145:
146: if(strstr(recvline, escapechar) != NULL) //종료문자열 입력시 처리
147: {
148: break;
149: }
150: else if(SYNC == recvline[0]) //동기신호
151: {
152: // 아무 일도 하지 않음
153: }
154: else
155: {
156: printf("%s", recvline); //화면 출력
157: }
158:
159: // 자식 <- 부모
160: if((size = read(fd[0], recvline, MAXLINE)) < 0)
161: {
162: printf("Error if read. \n");
163: close(client_sock);
164: exit(0);
165: }
166:
167: recvline[size] = '\0';
168:
169: if(strstr(recvline, escapechar) != NULL) //종료문자열 입력시 처리
170: {
171: //클라이언트에게 이스케이프 문자열 전송
172: write(client_sock, escapechar, sizeof(escapechar));
173: break;
174: }
175: else if(SYNC == recvline[0]) //동기신호
176: {
177: // 아무 일도 하지 않음
178: }
179: else
180: {
181: break; // 자식프로세스 종료
182: }
183: }
184: }
185:
186: close(server_sock);
187: close(client_sock);
188:
189: return 0;
190: }
191:
192: //시그널 처리함수
193: void timer(int sig)
194: {
195: int sync = SYNC;
196:
197: alarm(1); // 타이머 재시작
198:
199: write(fd[1], &sync, 1); // 파이프로 동기신호 발송
200: write(client_sock, &sync, 1); // 클라이언트로 동기신호 발송
201:
202: return ;
203: }
● Client
1: // talk_client_pipe.c
2: // TCP 1:1 채텅프로그램
3: // 프로세스가 올바르게 종료될 수 있도록 부모/자식 프로세스간
4: // 파이프를 연결하여 종료메시지를 건네준다.
5: // 특징: 서버와 클라이언트간 메시지가 아닌 동기제어신호를 전송함.
6: // read()가 블록이 되지 않으므로 두 가지 장치로 부터 수신가능.
7: //
8: // 작성자: 김수만
9: // 작성일자: 2011년 7월 21일
10: #include <stdio.h>
11: #include <string.h>
12: #include <stdlib.h>
13: #include <sys/types.h>
14: #include <signal.h>
15: #include <sys/socket.h>
16: #include <netinet/in.h>
17: #include <arpa/inet.h>
18: #include <sys/wait.h>
19:
20: #define MAXLINE 1024
21: #define SYNC 1
22:
23: char *escapechar = "exit"; //종료문자열
24: int s;
25: int fd[2]; //파이프
26:
27: void timer(int); //알람 시그널 처리함수
28:
29: int main(int argc, char *argv[])
30: {
31: char line[MAXLINE];
32: char sendline[MAXLINE];
33: char recvline[MAXLINE + 1];
34: char buffer[MAXLINE];
35: int n;
36: int size;
37: int comp;
38: int addr_size;
39: pid_t fork_ret;
40: static struct sockaddr_in server_addr;
41: // signal사용하기 위해 추가된 변수들
42: int state;
43: struct sigaction act;
44:
45: if(argc != 3)
46: {
47: printf("Usage : ./%s serverIP serverPORT \n", argv[0]);
48: exit(0);
49: }
50:
51: // pipe생성
52: state = pipe(fd);
53: if(-1 == state)
54: {
55: fprintf(stderr, "pipe() error. \n");
56: exit(1);
57: }
58:
59: // signal설정
60: act.sa_handler = timer;
61: sigemptyset(&act.sa_mask);
62: act.sa_flags = 0;
63:
64: //타이머 이벤트사용
65: if(SIG_ERR == sigaction(SIGALRM, &act, 0))
66: {
67: fprintf(stderr, "sigaction() error. \n");
68: exit(1);
69: }
70:
71: if(0 != state)
72: {
73: fprintf(stderr, "sigaction() error. \n");
74: exit(1);
75: }
76:
77: // 소켓 생성
78: if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
79: {
80: printf("Client: can't open stream socket. \n");
81: exit(0);
82: }
83:
84: // 소켓주소 구조체에 주소 세팅
85: bzero((char *)&server_addr, sizeof(server_addr)); //소켓주소 구조체 초기화
86: server_addr.sin_family = AF_INET;
87: server_addr.sin_addr.s_addr = inet_addr(argv[1]);
88: server_addr.sin_port = htons(atoi(argv[2]));
89:
90: // 서버에 연결 요청
91: if(connect(s, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
92: {
93: printf("Client: can't connect to server. \n");
94: exit(0);
95: }
96:
97: alarm(1); //1초 후에 알람시그널 발생
98: sleep(1);
99: fork_ret = fork();
100:
101: if(0 < fork_ret)
102: {
103: // 자식 프로세스는 키보드 입력을 클라이언트로 송신
104: while(fgets(sendline, MAXLINE, stdin) != NULL)
105: {
106: strcpy(buffer, "수만: ");
107: strcat(buffer, sendline);
108: size = strlen(buffer);
109: if(write(s, buffer, strlen(buffer)) != size)
110: {
111: printf("Error in write. \n");
112: }
113:
114: if(strstr(sendline, escapechar) != NULL) //종료문자열 입력시 처리
115: {
116: printf("Good bye. \n");
117: close(s);
118: sleep(3); //3초 후 종료
119: waitpid(-1, &state, WNOHANG); // wait()를 쓰면 더 좋음.
120: exit(0);
121: }
122: }
123: }
124: else if(0 == fork_ret)
125: {
126: // 부모 프로세스는 클라이언트로부터 수신된 메시지를 화면에 출력
127: while(1)
128: {
129: if((size = read(s, recvline, MAXLINE)) < 0)
130: {
131: printf("Error if read. \n");
132: close(s);
133: exit(0);
134: }
135:
136: recvline[size] = '\0';
137:
138: if(strstr(recvline, escapechar) != NULL) //종료문자열 입력시 처리
139: {
140: break;
141: }
142: else if(SYNC == recvline[0]) //동기신호
143: {
144: // 아무 일도 하지 않음
145: }
146: else
147: {
148: printf("%s", recvline); //화면 출력
149: }
150:
151: // 자식 <- 부모
152: if((size = read(fd[0], recvline, MAXLINE)) < 0)
153: {
154: printf("Error if read. \n");
155: close(s);
156: exit(0);
157: }
158:
159: recvline[size] = '\0';
160:
161: if(strstr(recvline, escapechar) != NULL) //종료문자열 입력시 처리
162: {
163: //클라이언트에게 이스케이프 문자열 전송
164: write(s, escapechar, sizeof(escapechar));
165: break;
166: }
167: else if(SYNC == recvline[0]) //동기신호
168: {
169: // 아무 일도 하지 않음
170: }
171: else
172: {
173: break; // 자식프로세스 종료
174: }
175: }
176: }
177:
178: close(s);
179:
180: return 0;
181: }
182:
183: //시그널 처리함수
184: void timer(int sig)
185: {
186: int sync = SYNC;
187:
188: alarm(1); // 타이머 재시작
189:
190: write(fd[1], &sync, 1); // 파이프로 동기신호 발송
191: write(s, &sync, 1); // 클라이언트로 동기신호 발송
192:
193: return ;
194: }
'내장형하드웨어 > 일일보고서' 카테고리의 다른 글
2011년7월22일_Talk Server & Client SIGALRM 시그널 사용시 문제점, 멀티플렉싱과 select( )의 사용법 (0) | 2011.07.22 |
---|---|
2011년7월22일_JAVA class복습과 생성자, 접근제어수식어와 getter/setter (0) | 2011.07.22 |
2011년7월21일_JAVA class, 연습문제들 (0) | 2011.07.22 |
2011년7월21일_IPC(Inter Process Communication) (0) | 2011.07.22 |
2011년7월20일_C언어 저장클래스(Storage class) 중 함수외부에 static저장클래스의 변수선언과 extern (접근속성(제한)과 전역변수 공개) (0) | 2011.07.21 |