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

+ Recent posts

티스토리 툴바