일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 티몬삼겹살데이
- 엑스퍼트생일축하해
- #부동산전자거래 #부동산전자계약 #부동산계약 #부동산전자계약방법 #부동산전자계약하는법 #부동산계약방법 #부동산중개수수료 #부동산중개수수료아끼기 #부동산복비아끼기
- lua interpreter
- lua install
- file open
- 엑스퍼트2주년
- 청량리역한양수자인192
- file write
- lua setup
- file read
- lua for windows
- 국토교통부
- C API
- Lua
- 등록임대주택
- 월세
- 프리미어 영상변환
- QT TCP
- meta table
- object
- TCP/IP
- C++ API
- 찾다죽는줄
- FILE TRANSFER
- #신혼부부 #결혼준비 #신혼부부희망타운신혼부부특별공급
- 수도권주택공급
- 프리미어 영상저장
- QTcpServer
- 중소규모택지
- Today
- Total
Value Creator의 IT(프로그래밍 / 전자제품)
Chapter 12 IO 멀티플렉싱 본문
* 멀티 프로세스 기반 서버와 차이점
멀티 프로세스 : 여러개의 프로세스가 여러개의 소켓을 핸들링(각 소켓에 대응하는 프로세스를 각각 만들어준다)
멀티플렉싱 : 하나의 프로세스가 여러개의 소켓을 핸들링
1. Select 함수를 이용하면 멀티플렉싱 서버 구현이 가능하다.
Select.c
select 함수 사용 예제
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/select.h>
#define BUF_SIZE 30
int main(int argc, char *argv[])
{
fd_set reads, temps; //fd_set 타입의 변수 선언
int result, str_len; //결과값, 길이값 변수
char buf[BUF_SIZE]; //문자열
struct timeval timeout; // timeout 시간?
FD_ZERO(&reads); //reads 변수 0으로 만들기
FD_SET(0, &reads); // 0 is standard input(console)
/*
timeout.tv_sec=5;
timeout.tv_usec=5000;
*/
while(1)
{
temps=reads; //select 함수 호출 전에 reads의 원본 데이터를 temps에 저장. select 함수 호출이 끝나면 변화가 생긴 파일 디스크립터를 제외하고는 모든 비트가 0으로 초기화됨.
timeout.tv_sec=5; //매번 반복해야함.
timeout.tv_usec=0;
result=select(1, &temps, 0, 0, &timeout); //select함수는 변화된 파일 디스크립터의 개수를 반환
if(result==-1) //select 함수에 에러 발생
{
puts("select() error!");
break;
}
else if(result==0) //select 함수의 반환값이 없음
{
puts("Time-out!");
}
else //select함수가 0이 아닌 값을 반환. 변화를 보인 파일 디스크립터가 표준입력이 맞는지 확인 후 표준입력으로부터 데이터를 읽어서 콘솔로 데이터 출력
{
if(FD_ISSET(0, &temps))
{
str_len=read(0, buf, BUF_SIZE);
buf[str_len]=0;
printf("message from console: %s", buf);
}
}
}
return 0;
}
2. 멀티플렉싱 서버 구현
echo_selectserv.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/select.h>
#define BUF_SIZE 100
void error_handling(char *buf);
int main(int argc, char *argv[])
{
int serv_sock, clnt_sock;
struct sockaddr_in serv_adr, clnt_adr;
struct timeval timeout;
fd_set reads, cpy_reads;
socklen_t adr_sz;
int fd_max, str_len, fd_num, i;
char buf[BUF_SIZE];
if(argc!=2) {
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
serv_sock=socket(PF_INET, SOCK_STREAM, 0);
memset(&serv_adr, 0, sizeof(serv_adr));
serv_adr.sin_family=AF_INET;
serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_adr.sin_port=htons(atoi(argv[1]));
if(bind(serv_sock, (struct sockaddr*) &serv_adr, sizeof(serv_adr))==-1)
error_handling("bind() error");
if(listen(serv_sock, 5)==-1)
error_handling("listen() error");
FD_ZERO(&reads);
FD_SET(serv_sock, &reads); //reads에 서버 소켓을 등록하고 있다. 서버 소켓의 데이터 수신 여부를 관찰할 것이다. 서버소켓에 수신된 데이터가 있다는 것은 연결요청이 있다는 뜻이다.
fd_max=serv_sock;
while(1)
{
cpy_reads=reads;
timeout.tv_sec=5;
timeout.tv_usec=5000;
if((fd_num=select(fd_max+1, &cpy_reads, 0, 0, &timeout))==-1)
break;
if(fd_num==0)
continue;
for(i=0; i<fd_max+1; i++) //상태변화가 있는 파일디스크립터를 찾는다.
{
if(FD_ISSET(i, &cpy_reads))
{
if(i==serv_sock) // connection request!
{
adr_sz=sizeof(clnt_adr);
clnt_sock=
accept(serv_sock, (struct sockaddr*)&clnt_adr, &adr_sz);
FD_SET(clnt_sock, &reads); //reads에 클라이언트와 연결된 소켓의 파일 디스크립터를 등록한다.
if(fd_max<clnt_sock)
fd_max=clnt_sock;
printf("connected client: %d \n", clnt_sock);
}
else // read message!
{
str_len=read(i, buf, BUF_SIZE);
if(str_len==0) // close request!
{
FD_CLR(i, &reads);
close(i);
printf("closed client: %d \n", i); //파일 디스크립터 번호를 출력한다.
}
else //수신한 데이터가 EOF인지 아닌지 확인한다.
{
write(i, buf, str_len); // echo!
}
}
}
}
}
close(serv_sock);
return 0;
}
void error_handling(char *buf)
{
fputs(buf, stderr);
fputc('\n', stderr);
exit(1);
}
위는 서버의 소스코드이고, Chapter 4 에서 했던 echo_client.c를 클라이언트 소스코드로 활용해서 상호간 통신을 확인해보면 된다.
[서버]
a@a:~/Desktop/NP/manual/TCPIP_Src/Chapter12$ gcc echo_selectserv.c -o selserv
a@a:~/Desktop/NP/manual/TCPIP_Src/Chapter12$ ./selserv 9190
connected client: 4
closed client: 4
connected client: 4
connected client: 5
[첫 번째 클라이언트]
a@a:~/Desktop/NP/manual/TCPIP_Src/Chapter12$ ./client 127.0.0.1 9190
Connected...........
Input message(Q to quit): 123123
Message from server: 123123
Input message(Q to quit): 34432
Message from server: 34432
Input message(Q to quit): ^C
[두 번째 클라이언트]
a@a:~/Desktop/NP/manual/TCPIP_Src/Chapter12$ ./client 127.0.0.1 9190
Connected...........
Input message(Q to quit): asdasdasd
Message from server: asdasdasd
Input message(Q to quit):
'1. 프로그래밍 > 4) Network' 카테고리의 다른 글
Chapter 14 추후 작성 (0) | 2019.11.07 |
---|---|
Chapter 13 입출력 함수(send, recv, read, write) (0) | 2019.11.06 |
Chapter 11 프로세스 간 통신 (0) | 2019.10.31 |
Chapter 10 멀티 프로세스 기반의 서버 구현 (0) | 2019.10.30 |
Chapter 9 소켓의 다양한 옵션 - 추후 작성 (0) | 2019.10.30 |