멀티태스킹 : fork() 함수를 이용하여서 1 Client <-> 1 Server(자식서버) , 독립적인 1:1 형태로 통신을 하는 방법이다.
fork() 함수란?
현재 실행되는 프로세스에 대해 복사본 프로세스를 생성합니다.
fork()함수를 호출하고 성공하면 pid 변수값만 다른 완전히 똑 같은 프로세스가 생성됩니다. 그러므로 지금 프로그램이 원래 실행되었던 부모 프로세스인지, 아니면 새로 생성된 자식 프로세스인지는 fork()에서 반환한 값으로 확인합니다.
헤더 |
unistd.h |
형태 |
pid_t fork(void); // 여기서 pid_t 는 unsigned int 형 |
반환 |
pid_t |
실행에 실패하면 -1 을 반환. 부모에게는 새로 생성된 자식 프로세스 PID가 반환되며, 자식 프로세스에는 0이 반환됩니다 | |
예제 :
원래 실행되었던 부모 프로세스 |
fork()로 생성된 자식 프로세스 |
int main()
{
int counter = 0;
pid_t pid;
printf( "작식 프로세스 생성");
pid = fork(); ---> 자식 프로세서 생성
---> pid 값은 자식 프로세스의 pid 값
switch( pid)
{
case -1 :
{
printf( "자식 프로세스 생성 실패\n");
return -1;
}
case 0 :
{
printf( "저는 자식 프로세스....\n");
while( 1 )
{
printf( "자식: %d\n", counter--);
sleep( 1);
}
}
default :
{
printf( "저는 부모 프로세스로..");
printf( "자식 프로세스의 pid는..", pid);
while( 1 )
{
printf( "부모: %d\n", counter++);
sleep( 1);
}
}
}
} |
int main()
{
int counter = 0;
pid_t pid;
---> 부모와 똑 같은 프로세스가 그대로 복사되므로
---> 전역 변수 값에서 로컬 변수 값까지 모두
---> 복사됩니다.
---> 대신에 딱 하나, pid 값만 0 값을 갖습니다.
switch( pid)
{
case -1 :
{
printf( "자식 프로세스 생성 실패\n");
return -1;
}
case 0 :
{
printf( "저는 자식 프로세스로....\n");
while( 1 )
{
printf( "자식: %d\n", counter--);
sleep( 1);
}
}
default :
{
printf( "저는 부모 프로세스로...\n");
printf( "자식 프로세스의 pid는...", pid);
while( 1 )
{
printf( "부모: %d\n", counter++);
sleep( 1);
}
}
}
}
|
|
#include <stdio.h> // pritnf, fprintf #include <sys/socket.h> // socket, bind, connect #include <arpa/inet.h> // sockaddr_in, inet_ntoa #include <stdlib.h> // atoi #include <string.h> // memset #include <unistd.h> // close
#define MAXPENDING 5 // Maximum outstanding connection requests
int main () { int servSock; // Socket descriptor for server int clntSock; // Socket descriptor for client struct sockaddr_in echoServAddr; // Local address struct sockaddr_in echoClntAddr; // Client address unsigned short echoServPort; // Server port number unsigned int clntLen; // Length of client address data structure int iRet; unsigned char ucBuffer[500]; pid_t ui_MomID;
ui_MomID = getpid(); echoServPort = 9999; // Server Port Number
// 1. 소켓 생성(랑데뷰 소켓) Create socket for incoming connections servSock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); // Protocol Family_Internet if (servSock < 0) // error { printf ("socket() failed\n"); return 0; } // 2. 구조체 생성 Construct local address structure memset ( &echoServAddr, 0, sizeof(echoServAddr) ); // Zero out structure // memory setting ( 주소 , 채울 숫자, 몇개 ) echoServAddr.sin_family = AF_INET; // Internet address family echoServAddr.sin_addr.s_addr = htonl (INADDR_ANY); // Any incoming interface // host to network long ( 크기 ) Big Endian 으로 바꿔주는 함수 // INADDR_ANY 는 0으로 define 되어 있다 ( 자동:클라이언트를 만들때 ) // INADDR_ANY 대신에 내 IP의 실제 주소를 넣는 방법도 있다 ( 수동:서버를 만들때 ) echoServAddr.sin_port = htons (echoServPort); // Local port (2 byte) // host to network short ( 크기 ) Big Endian 으로 바꿔주는 함수
// 3. BIND 소켓에 구조체를 적용 Bind to the local address iRet = bind(servSock, (struct sockaddr*) &echoServAddr, sizeof (echoServAddr)); // 신형을 구형으로 바꿈 = casting 연산 if (iRet < 0) // error { printf ("bind() failed\n"); close (servSock); return 0; } // 4. LISTEN Mark the socket so it will listen for incoming connections iRet = listen(servSock, MAXPENDING); // MAXPENDING 최대 동시 접속자 수 if (iRet < 0) { printf ("listen() failed\n"); close (servSock); return 0; } while (1) { if(ui_MomID == getpid()) { // 5. ACCEPT Wait for a client to connect clntLen = sizeof (echoClntAddr); // Set the size of the in-out parameter clntSock = accept (servSock, (struct sockaddr *) &echoClntAddr, &clntLen); // Communication Socket (client 의 정보가 저장) if (clntSock < 0) { printf ("accept() failed\n"); return 0; } // clntSock is connected to a client printf ("Handling client ip %s\n", inet_ntoa(echoClntAddr.sin_addr)); printf ("Handling client port %d\n", ntohs(echoClntAddr.sin_port)); fork(); // 서버를 복제함. if(ui_MomID == getpid()) // 부모에게는 새로 생성된 자식 프로세스 PID가 반환되며, 자식 프로세스에는 0이 반환된다.
{ close(clntSock); // 부모서버이므로 clntSock 을 닫아준다. } else { close(servSock); // 자식서버이므로 servSock 을 닫아준다. } } else { iRet = read (clntSock, ucBuffer, 499); // client로부터 입력 대기 ucBuffer[iRet] = 0; write (1, ucBuffer, iRet); write (clntSock, ucBuffer, iRet); if ('q' == ucBuffer[0]) / q 로 서버끔. { close (servSock); break; }
} } close (servSock); close (clntSock);
return 0; } |