그래픽 & 멀티미디어
글 수 111
2007.12.27 00:27:44 (*.33.84.154)
48243
이전 시간에는 타이머를 이용해서 직접 소켓을 읽었기 때문에 상대방이 자료를 전송하기 전까지는 프로그램이 block되어 버리는 문제가 있었습니다.
uds 자료만 가공한다면 문제 없겠지만 UDS가 IPC의 방법 중 하나라면 이렇게 사용되는 경우가 거의 없겠죠. ^^ 그러므로 block되는 것을 피하기 위해 POLL을 이용하도록 하겠습니다. POLL을 처음 접하시는 분은 꼭 아래의 글을 먼저 보십시오.
프로그램 코딩 시작
이전 프로그램에 POLL을 위한 코드 부분만 추가됩니다. 그래도 작업 순서대로 글을 올리겠습니다.
- 프로제트 파일 생성, "C++ Project"를 선택합니다.

- 적당한 프로젝트 이름을 입력합니다.

- 프로젝트 파일을 저장합니다.

- 폼 이름을 지정합니다. 이 이름이 클래스 이름이 되므로 적당한 이름을 지정해 줍니다. 여기서는 frmMain으로 입력하겠습니다.

- 필요한 위젯을 배치합니다.

- labCounter는 타이머 작동을 확인하기 위해 준비했으며, 타이머가 작동할 때 마다, 숫자가 하나씩 증가할 것입니다.
- labReceive 라벨은 수신된 자료를 출력하겠습니다.
- 폼 생성 후에 실행할 init()함수와 타이머의 슬롯함수를 등록합니다.

- 전체 소스입니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/poll.h>
#include <qapplication.h>
#include <qtimer.h>
#include <qmessagebox.h>
#define SOCK_LOCALFILE "/tmp/uds_a"
#define BUFF_SIZE 1024
char buffReceive[BUFF_SIZE+5];
size_t szAddr;
struct sockaddr_un addrLocal;
struct sockaddr_un addrGuest;
QTimer *tmrCenter;
int sock;
int nCounter;
struct pollfd poll_events; // POLL을 위한 변수 선언
// 폼이 생성된 후에 불리워지는 함수, init()입니다.
// 타이머를 생성하고 소켓을 생성하겠습니다.
void frmMain::init()
{
// 타이머를 생성하고 카운터를 0으로 초기화 합니다.
tmrCenter = new QTimer( this);
nCounter = 0;
// UDS에서 사용할 파일이 존재하면 삭제합니다.
if ( 0 == access( SOCK_LOCALFILE, F_OK))
unlink( SOCK_LOCALFILE);
// UDS 소켓을 생성합니다.
sock = socket( PF_FILE, SOCK_DGRAM, 0);
if( -1 == sock)
{
QMessageBox::information( this, "UDS", "I cannot build a socket!!");
return;
}
// UDS 소켓 정보를 완성하고 bind()함수를 호출하여
// 다른 시스템에서 전송되어 오는 자료를 수신할 준비를 합니다.
memset( &addrLocal, 0, sizeof( addrLocal));
addrLocal.sun_family = AF_UNIX;
strcpy( addrLocal.sun_path, SOCK_LOCALFILE);
if( -1 == bind( sock, (struct sockaddr*)&addrLocal, sizeof( addrLocal)) )
{
QMessageBox::information( this, "UDS", "bind error!!");
return;
}
// POLL 이벤트를 등록합니다.
poll_events.fd = sock;
poll_events.events = POLLIN;
poll_events.revents = 0;
// 타이머와 종료 버튼의 시그널에 대해 슬롯을 연결합니다.
connect( tmrCenter, SIGNAL( timeout()), this, SLOT( onCenterTimer()));
connect( btnClose, SIGNAL( clicked()), qApp, SLOT( quit()));
// 타이머를 가동합니다.
tmrCenter->start(500, false);
}
// init() 함수에서는 타이머와 소켓을 준비했습니다.
// 이제 타이머 가동되면 labCounter에 숫자를 증가하여 출력하고,
// 상대방으로부터 수신된 자료가 있다면 반송하겠습니다.
void frmMain::onCenterTimer()
{
int poll_state;
int szRead;
// 카운터를 출력하고 증가합니다.
labCounter->setNum( nCounter++);
// poll()함수로 수신된 자료가 있는지를 확인합니다.
// 수신된 자료가 있을 때에만 자료를 수신하기 때문에
// 프로그램이 block 되지 않습니다.
poll_state = poll( ( struct pollfd*)&poll_events, 1, 500);
if ( 0 < poll_state)
{
if ( poll_events.revents & POLLIN)
{
szAddr = sizeof( addrGuest);
memset( buffReceive, 0, BUFF_SIZE);
szRead = recvfrom( sock, buffReceive, BUFF_SIZE, 0 ,
( struct sockaddr*)&addrGuest, &szAddr);
// 여기까지 실행되었다면 자료가 수신된 것입니다.
// 화면의 라벨에 출력하고
buffReceive[szRead] = '\0';
labReceive->setText( buffReceive);
// 상대방 시스템으로 전송합니다.
sendto( sock, buffReceive, szRead+1, 0,
( struct sockaddr*)&addrGuest, szAddr);
}
}
}
프로그램 완성
main()함수를 위해 main.cpp를 생성하고 컴파일하면 모든 작업이 끝납니다.
프로젝트를 빌드하기 위해서 main.cpp를 생성합니다. File >> New메뉴를 선택합니다. main.cpp를 선택합니다.
frmMain을 선택하고 프로젝트를 빌드합니다.
]# qmake ]# make ]# ./uds -> 프로젝트 파일 이름
프로그램 실행
프로그램을 실행하면 Count 값이 계속 증가되는 것을 보실 수 있습니다.
.
프로그램 테스트를 위해 .tester_user 폴더에 uds.c 파일을 실행합니다.
]$ gcc uds.c ]$ ./a.out forum.falinux.com
이렇게 UDS로 문자열을 전송하면 frmMain 윈도우에 전송한 문자열이 출력됩니다.



