11. 11 월 컴퓨터네트워크2 멀티태스킹


서버의 행동 중 socket(), bind(), listen()의 과정을 CreateTCPServerSocket()이란 함수로 묶고, accept()를 AcceptTCPConnection()으로, receive(), send()를 HandlingTCPClient()라는 함수로 묶어서 사용.


# 클라이언트당 프로세스

멀티태스킹을 위해 fork()를 이용하여 자식 프로세스를 생성한다. 이 자식 프로세스는 receive(), send()의 역할을 수행하며 Client는 자식프로세스에게 send()하게 된다. 자식 프로세스가 종료되어도 이 프로세스가 자동으로 사라지는 것이 아니라 waitpid() 호출을 통해 좀비프로세스를 수확해야 자원이 회수된다.

 

# 클라이언트당 쓰레드

접속하는 클라이언트당 프로세스를 생성하는 방법은 자원이 많이 사용된다. 운영체제에서는 메모리, 스택, 파일/소켓 식별자들 등을 부모 프로세스의 상태 전체를 복제해야하므로 클라이언트당 쓰레드의 방법으로 사용하는 것이 좋다.


# 제한 멀티태스킹

시스템 자원의 크기에 적합한 접속 클라이언트 수를 넘을 경우 시스템 전체 자원에 대해 과부하가 발생하게 된다. 이를 막기 위해 제한 멀티태스킹을 사용한다.

이건 다음 주에...







저작자 표시 비영리 변경 금지
신고

'Network' 카테고리의 다른 글

멀티태스킹(Multi tasking)  (0) 2013.11.11
신호(Signals)  (0) 2013.11.04
UDPEchoServer  (0) 2013.10.30
소켓옵션들  (0) 2013.10.28
tcp/ip 소켓 프로그래밍 함수 소개  (0) 2013.09.16

UDPEchoClient에서 클라이언트가 Sendto() 후 서버의 Sendto()를 기다리는 동안 block되지 않도록 하는 방법

1) non-blocking socket - 서버측

2) asynchronous I/O - 서버측

3) Timeout - 클라이언트측


1)

Process에서 InterruptSignalHandler 실행 중 사용자가 Ctrl+C와 같은 인터럽트 입력 시 System에서 SIGINT가 들어오게되고 InterruptSignalHandler() 내부에서 printf("Interrupt Received"); 와 같은 문자열 출력 후 for(;;)문 내부의 pause가 실행되어 프로그램이 정지된다.


2) 

서버에서 bind() 이후 대기하는 동안 다른 작업(3초마다 . 출력)을 하게 된다. 이 때 클라이언트로부터 요청이 들어와 OS로 부터 SIGIO 신호가 들어오게 되면 서버는 작업을 멈추고 해당 요청에 대한 작업을 수행한다.


3)

UDPClient쪽에 해당함. 클라이언트의 요청에도 서버에서 응답이 없을 경우 타이머를 작동 시켜 다시 데이터를 보내게 되고 계속 응답이 없으면 연결을 끝낸다.

클라이언트는 Sendto() 이후 alarm(TIMEOUT_SECS)로 서버의 응답을 얼마나 기다릴지 설정한다.

이후 설정한 시간동안 응답이 없으면 OS에서 EINT라는 에러메시지를 통해 TIMEOUT를 알리게 된다.

이 과정을 반복하다가 클라이언트에서 설정한 MAXTRIES의 횟수를 넘게 되면 "Sendto() failed" 출력 후 연결을 종료.


※ sigfillset()

int sigfillset(sigset_t *set);

특정 신호가 아닌 모든 신호를 감지하겠다는 의미로 시그널 셋에 모든 시그널을 포함시키는 함수이다.







저작자 표시 비영리 변경 금지
신고

'Network' 카테고리의 다른 글

멀티태스킹(Multi tasking)  (0) 2013.11.11
신호(Signals)  (0) 2013.11.04
UDPEchoServer  (0) 2013.10.30
소켓옵션들  (0) 2013.10.28
tcp/ip 소켓 프로그래밍 함수 소개  (0) 2013.09.16

#include <stdio.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>


#define ECHOMAX 255


void DieWithError(char *errorMessage);


int main(int argc, char *argv[])

{

int sock;

struct sockaddr_in echoServAddr;

struct sockaddr_in echoClntAddr;

unsigned int cliAddrLen;

char echoBuffer[ECHOMAX];

unsigned short echoServPort;

int recvMsgSize;


if (argc != 2)

{

fprintf(stderr,"Usage: %s <UDP SERVER PORT> \n", argv[0]);

exit(1);

}

echoServPort = atoi(argv[1]);


if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)

DieWithError("socket() failed");


memset(&echoServAddr, 0, sizeof(echoServAddr));

echoServAddr.sin_family = AF_INET;

echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);

echoServAddr.sin_port = htons(echoServPort);


if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)

DieWithError("bind() failed");

for (;;)

{


cliAddrLen = sizeof(echoClntAddr);


if ((recvMsgSize = recvfrom(sock, echoBuffer, ECHOMAX, 0,

(struct sockaddr *) &echoClntAddr, &cliAddrLen)) < 0)

DieWithError("recvfrom() failed");

printf("Handling client %s \n", inet_ntoa(echoClntAddr.sin_addr));


if (sendto(sock, echoBuffer, recvMsgSize, 0,

(struct sockaddr *) &echoClntAddr, sizeof(echoClntAddr)) != recvMsgSize)

DieWithError("sendto() sent a different number of bytes than expected");

}

}







저작자 표시 비영리 변경 금지
신고

'Network' 카테고리의 다른 글

멀티태스킹(Multi tasking)  (0) 2013.11.11
신호(Signals)  (0) 2013.11.04
UDPEchoServer  (0) 2013.10.30
소켓옵션들  (0) 2013.10.28
tcp/ip 소켓 프로그래밍 함수 소개  (0) 2013.09.16

소켓 옵션의 값을 변경함으로써 소켓의 수신버퍼 크기 변경 가능

getsockopt() : 소켓의 옵션 값을 참조

setsockopt() : 소켓의 옵션 값을 지정


int getsockopt(int socket, int level, int optName, void *optVal, Unsigned int * optLen)

int setsockopt(int socket, int level, int optName, const void *optVal, Unsigned int * optLen)


--- 소켓 버퍼크기 지정 프로그램 ---

int rcvBufferSize;

int sockOptSize;


sockOptSize = sizeof(rcvBufferSize);

if(getsockopt (sock, SOL_SOCKET, SO_RCVBUF, &rcvBufferSize, &sockOptSize) <0)

DieWithError("");


..... 생략됨


-----------------------------------



신호(Signals)

프로그램들에게 어떤 사건들이 발생했다는 것을 알리는 체계를 제공

예 : 사용자가 인터럽트 문자(리눅스의 Ctrl+C)를 입력했을 때, 타이머 만료


신호가 수행중인 프로그램에 전달될 때 다음 네가지 중 하나가 발생

1. 신호가 무시

2. 프로그램이 운영체제에 의해 강제저긍로 종료

3. 프로그램에 의해 지정된 신호처리 루틴이 수행

4. 신호가 블록 : 프로그램이 전달을 허용하는 조치를 취할 떄까지 어떤 효과를 내는 것을 막음


--- 신호 처리 프로그램 ---

// sigaction.c


#include <stdio.h>

#include <signal.h>

#include <unistd.h>

#include <stdlib.h>


void DieWithError(char *errorMessage);

void InterruptSignalHandler(int signalType);    // 신호에 대한 처리를 해줄 함수


int main(int argc, char *argv[])

{

struct sigaction handler;    //신호 처리를 위한 구조체 핸들러 선언


handler.sa_handler = InterruptSignalHandler;    //신호 구조체 선언

if(sigfillset(&handler.sa_mask) <0)    //신호를 어떻게 처리할 지 선언(마스크 = 블럭)

DieWithError("sigfillset() failed");

handler.sa_flags = 0;


if (sigaction(SIGINT, &handler, 0) <0)

DIeWithError("sigaction() failed");


for(;;)

pause();


exit(0);

}


void InterruptSignalHandler(int signalType)

{

printf("Interrupt Received. Exiting program.\n");

exit(1);

}

/* 위 함수와 교체 부분

void InterruptSignalHandler(int ignored)

{

printf("Interrupt Received.\n");

sleep(3);

}

*/

※ 시스템 상에서 인터럽트를 2번만 받기 떄문에 Ctrl+C를 3번 연속 눌러도 Interrupt Received 메시지는 2번만 출력됨.







저작자 표시 비영리 변경 금지
신고

'Network' 카테고리의 다른 글

멀티태스킹(Multi tasking)  (0) 2013.11.11
신호(Signals)  (0) 2013.11.04
UDPEchoServer  (0) 2013.10.30
소켓옵션들  (0) 2013.10.28
tcp/ip 소켓 프로그래밍 함수 소개  (0) 2013.09.16

2.1 생성과 해지

socket()

tcp나 udp 통신을 하기 위해 사용

 

파라미터

int socket(int protocolFamliy, int type, int protocol)

int protocolFamliy

소켓의 패밀리 결정

인터넷 프로토콜 패밀리 프로토콜을 사용하는 소켓 : PF_INET

int type

소켓의 형태를 지정(데이터 전송의 의미를 결정)

SOCK_STREAM : TCP

SOCK_DGRAM : UDP

int protocol

특정 종단간 프로토콜을 나타냄

tcp 스트림 소켓 : IPPROTO_TCP

udp 데이터그램 소켓 : IPPROTO_UDP

0으로 설정할 경우 : 지정된 프로토콜 패밀리 및 형태를 위한 디폴트 종단간 프로토콜 사용

반환값 : 음의 값이 아니면 성공, -1은 실패

 

close()

소켓을 종료할 때 호출하는 함수(할당된 자원 회수)

사용하지 않을 소켓을 파라미터로 지정

 

파라미터

int close(int socket)

반환값 : 성공시 0, 실패시 -1

 

2.2 주소지정

소켓을 사용하는 프로그램이 커널에 인터넷 주소와 포트를 지정하는 방법

클라이언트는 통신할 서버의 주소와 포트를 지정해야 함

 

소켓 API

소켓과 관련된 주소를 지정하기 위한 데이터 형태

sockaddr 구조체

struct sockaddr

{

unsigned short sa_family;    //패밀리 추가

char sa_data[14];              //패밀리 특정 주소 정보

}

 

...중간 생략...정리할 부분

 

* 2.2 주소 지정(p.9)

구조체 sockaddr_in 중요

위 구조의 도식화 -> p.7

 

2.3 TCP 클라이언트

서버측 함수

socket()

bind() 소켓과 포트번호를 결합시켜주는 것

listen()

accept() <- 서버는 여기까지 수행한 후 클라이언트 대기

receive() 클라이언트에서 데이터를 받음

send() 요청에 대해 응답

close() 통신 종료

 

클라이언트측 함수

socket()

connet() 서버로 연결

send() 데이터 전송

receive() 서버로부터 응답 받음

close() 통신 종료

 

connet()

파라미터

int connet(int socket, struct sockaddr *foreignAddress, unsigned int addressLength)

socket

socket()에 의해 생성된 식별자

foreignAddress

소켓 API가 총괄적임

sockaddr의 포인터로 선언

(struct sockaddr *) &echoServAddr : &echoServAddr의 주소로부터 struct sockadr *의 구조체를 갖는다

addressLength

주소 구조체의 길이를 나타냄

고정적으로 sizeof(struct sockaddr_in)으로 주어짐

 

send()

모든 데이터를 다 보낼 떄 까지 블록(block)되는 것

※ call by reference와 call by value의 차이점 알아보기

파라미터(call-by-reference 방식으로 주소만 가져다 씀)

int send(int socket, const void * msg, unsigned int msgLength, int flags)

socket

연결된 소켓의 식별자

msg

send()로 전송하는 메시지

msgLength

메시지의 길이, 바이트 단위

flags

소켓 호출의 디폴트 도작을 변경시키는 방법을 제공(디폴트 동작 : 0)

 

반환값

정상 : 전송한 데이터의 바이트 수

비정상 : -1

 

char *echoString의 의미 : 어떤 주소(echoString)로부터 시작하는 내용이 char형을 가진다.

 

recv()

어느 정도의 바이트가 이동될 때까지 블록(block)되는 것

파라미터

int recv(int socket, void * rcvBuffer, unsigned int bufferLength, int flags)

socket

연결된 소켓의 식별자

rcvBuffer

받은 데이터를 저장하는 버퍼를 가리킴

bufferLength

버퍼의 길이, 한 번에 받을 수 있는 최대 바이트 수

flags

소켓 호출의 디폴트 도작을 변경시키는 방법을 제공(디폴트 동작 : 0)

 

반환 값

정상 : 전송한 데이터의 바이트 수

비정상 : -1

close() 함수를 호출하여 종료

 

TCP Client

char *servIP 서버의 ip를 외부 인자를 char형으로 우선 받은 뒤 숫자로 바꿔서 struct sockaddr_in echoServAddr에서 사용함

 






 

저작자 표시 비영리 변경 금지
신고

'Network' 카테고리의 다른 글

멀티태스킹(Multi tasking)  (0) 2013.11.11
신호(Signals)  (0) 2013.11.04
UDPEchoServer  (0) 2013.10.30
소켓옵션들  (0) 2013.10.28
tcp/ip 소켓 프로그래밍 함수 소개  (0) 2013.09.16

+ Recent posts

티스토리 툴바