블로그 이미지
hengki
우쭈쭈우쭈쭈

calendar

  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        

'2009/06'에 해당되는 글 6

  1. 2009/06/26 밥돌 상장.(1)
  2. 2009/06/12 C++ 에코 클라이언트.
  3. 2009/06/12 C++ 윈도우 소켓 - 비동기 에코 서버
  4. 2009/06/09 컴공 친구의 avr 도전기 - 1(2)
  5. 2009/06/08 CRT 피봇..(2)
2009/06/26 20:50 Hengki's Story


학교 식단을 시간에 맞추어 sms로 전송해주는 프로그램.
저작자 표시
posted by hengki
TAG 밥돌
2009/06/12 12:58 Hengki's Program/C++
 에코 서버를 찾아 들어오신분은 꼭 에코 클라이언트가 필요할것 같다는 생각에.. 없는 소스 짜서 올려봄니다.



#define BUFSIZE 1024
#define PORT 3000
#define IP "192.168.2.12"

// 해더파일 선언
#include <winsock2.h>
#include <iostream>

using namespace std;

// ws2_32.lib 링크
#pragma comment(lib, "ws2_32.lib")

class socketClient
{
private:
WSADATA wsaData;
SOCKET hSocket;
char message[BUFSIZE];
int strLen;
SOCKADDR_IN servAddr;
void ErrorHandling(char *message);

public:
int StartClient();

};

int socketClient::StartClient()
{
// 윈속 초기화 (성공시 0, 실패시 에러 코드리턴)
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){
ErrorHandling("WSAStartup() error!"); 
}

// 소켓 생성 (성공시 핸들을, 실패시 "INVALID_SOCKET" 반환)
hSocket=socket(PF_INET, SOCK_STREAM, 0);   
// 소켓 생성 실패 처리
if(hSocket == INVALID_SOCKET){
ErrorHandling("socket() error");
}

// 매모리 초기화
memset(&servAddr, 0, sizeof(servAddr));

// 소켓 통신을 위한 기본 정보 
servAddr.sin_family=AF_INET;
servAddr.sin_addr.s_addr=inet_addr(IP);
servAddr.sin_port=htons(PORT);

// 서버 커넥트
if(connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr))==SOCKET_ERROR){
ErrorHandling("connect() error!");
}

// 루프
while(1) {

cout<<"전송할 메시지를 입력하세요 (q to quit) : ";
cin>>message;

// q신호 일때 소켓을 끝냄
if(!strcmp(message,"q")) break;
// 메시지전송
send(hSocket, message, (int)strlen(message), 0);

// 메시지 수신
strLen=recv(hSocket, message, BUFSIZE-1, 0); /* 메시지 수신 */
// 받은 값의 끝에 널값을 붙임.
message[strLen]=0;
cout << message <<endl;
}

// 소켓 종류 신호전송
closesocket(hSocket);

// 할당 받은 리소스 반환.
WSACleanup();
return 0;
}

void socketClient::ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}




/************************************
/* 
/* main
/*
*/
int main(){

// 클라이언트 인스턴트
socketClient client;
// 시작
client.StartClient();
}
저작자 표시
posted by hengki
2009/06/12 03:48 Hengki's Program/C++
소스만 바로 받아서 보는게 속편하겠죠 ㅎㅎ



 음.. 비쥬얼스튜디오 2005에서 컴파일 했을때 워닝 하나 없이 잘돌아간 소스입니다.  주석에도 있듯이 열혈강의 TCP/IP 예제를 클레스화 한것이고요. WSAEventSelect 모델 기반의 소켓 서버입니다. 쉽게 풀어 쓰면 소켓의 상태의 변화가 있을때 WSAEventSelect 이란 놈(API)가 알아채서 그상황에 맞는 행동을하는것입니다. 멀티 쓰레드 서버 인데 처리 방식이 비동기 식 이라고 생각하면 편할듯 하네요. 

 비동기! 비동기? 라고 계속 말하는데 "그게 뭐야?" 라는 의문을 가지는 분께 누구나 알아 먹는 설명! 간단 명료한 행기표 설명 따라 들어갑니다. ㅋㅋㅋ 

 저녁 준비하던 엄마가 콩나물 500원 어치를 사오라는  심부름일 시켰습니다. 행기는 동내 슈퍼로 콩나물을 사러 갑니다. 여기서 집중!!

1. 엄마는 콩나물이 올때까지 아무일도하지 않고 행기를 기다린다.
2. 엄마는 콩나물이 올때까지 다른일을 하고 행기가 돌아온뒤 콩나물 요리를 한다.

1번은 동기식입니다. 일이 발생했을때 그일이 다처리된후 나머지 일들을 처리 하는 방법이지요.
2번은 비동기식입니다. 일이 발생했을때 그일이 처리 될때까지 나머일을 처리하며 방법 입니다.

말로만 들으면 비동기가 무조건 좋다! 라고 생각할수 있지만 상황에 따라 잘 골라써야겠죠. 

 소스 설명을 좀더 붙이 면 "//루프" 라고 주석 처리된부분에서 계속 반복문을 돌면서 소켓의 상태를 살펴서 이놈이 지금  처음 접속인지, 데이터를 보내오는지, 접속을 종류하는지를 살피고 그에따른 if문을 찾아 들어가는거지요. while문 안쪽의 for문이 쓰레드가 되는 부분이겠죠. 

소켓의 구조(단계?) 를 알고 구조만 살피면 쉽게 이해되는 소스입니다.

아참!! 레포트로 배껴 가지마세요.. 책에 있는 내용이라서 배껴쓰면 교수님이 금방 알아 보실거라는.. 그리고 쓰레드는 60개 정도가 한개일것 같네요.



//////////////////////////////////////////////////////////////////////////////////////////////////
// 
// 비동기 소켓 서버
// 열혈강의 TCP/IP 20장의 예제를 클레스화
// 일단 에코 서버이며. 167 번째 줄에서 서버에서 해줄 코드를 입력하면 될듯..
//

#define BUFSIZE 100 // 받아올 데이터 최대 크기
#define PORT 3000 // 포트번호 할당

// 해더파일 선언
#include <winsock2.h>
#include <iostream>

using namespace std;

// ws2_32.lib 링크
#pragma comment(lib, "ws2_32.lib")

class socketServer
{
private:
// 변수 선언
WSADATA wsaData;
SOCKET hServSock;
SOCKADDR_IN servAddr;

    //소켓 핸들배열 - 연결 요청이 들어올 때마다 생성되는 소켓의 핸들을 이 배열에 저장.     SOCKET hSockArray[WSA_MAXIMUM_WAIT_EVENTS];
 
SOCKET hClntSock;
SOCKADDR_IN clntAddr;

WSAEVENT hEventArray[WSA_MAXIMUM_WAIT_EVENTS]; // 이벤트 배열 
WSAEVENT newEvent;
WSANETWORKEVENTS netEvents;

int clntLen;
int sockTotal;
int index, i;  
char message[BUFSIZE];
int strLen;

void CompressSockets(SOCKET* hSockArray, int omitIndex, int total);
void CompressEvents(WSAEVENT* hEventArray, int omitIndex, int total);
void ErrorHandling(char *message);

public:
socketServer();
int StartServer();
};

socketServer::socketServer()
{
sockTotal=0;
}

int socketServer::StartServer()
{

// 윈속 초기화 (성공시 0, 실패시 에러 코드리턴)
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){
ErrorHandling("WSAStartup() error!");
}

// 소켓 생성 (성공시 핸들을, 실패시 "INVALID_SOCKET" 반환)
hServSock = socket(PF_INET, SOCK_STREAM, 0);
// 소켓 생성 실패 처리
if(hServSock==INVALID_SOCKET){
ErrorHandling("socket() error");
}


// 소켓 통신을 위한 기본 정보 
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(PORT);


// 주소와 Port 할당 (바인드!!)
if(bind(hServSock, (struct sockaddr *) &servAddr, sizeof(servAddr))==SOCKET_ERROR){
ErrorHandling("bind() error");
}


// 이벤트 발생을 확인 (성공시 0, 실패시 "SOCKET_ERROR" 반환)
newEvent = WSACreateEvent();
if(WSAEventSelect(hServSock, newEvent, FD_ACCEPT)==SOCKET_ERROR){
ErrorHandling("WSAEventSelect() error");
}


// 연결 대기 요청 상태로의 진입 (신호가 들어올때까지 대기)
if(listen(hServSock, 5)==SOCKET_ERROR){
ErrorHandling("listen() error");
}
  

// 서버 소켓 핸들 정보
hSockArray[sockTotal]=hServSock;

// 이벤트 오브젝트 핸들 정보
hEventArray[sockTotal]=newEvent;

// 전체 소켓수
sockTotal++;

  

// 루프
while(1)
{
// 이벤트 종류 구분하기(WSAWaitForMultipleEvents)
index = WSAWaitForMultipleEvents(sockTotal, hEventArray, FALSE, 
WSA_INFINITE, FALSE);
index = index-WSA_WAIT_EVENT_0;

for(i=index; i<sockTotal; i++)
{
index = WSAWaitForMultipleEvents(1, &hEventArray[i], TRUE, 0, FALSE);
if((index==WSA_WAIT_FAILED || index==WSA_WAIT_TIMEOUT)) continue;
else
{
index = i;
WSAEnumNetworkEvents(hSockArray[index],
 hEventArray[index], &netEvents);

// 초기 연결 요청의 경우.
if(netEvents.lNetworkEvents & FD_ACCEPT) 
{
if(netEvents.iErrorCode[FD_ACCEPT_BIT] != 0)
{
puts("Accept Error");
break;
}

clntLen = sizeof(clntAddr);
// 연결을 수락 
    // (accept | 성공시 소켓핸들 실패시 "INVALID_SOCKET" 반환)
hClntSock = accept(hSockArray[index],
(SOCKADDR*)&clntAddr, &clntLen);

// 이벤트 커널 오브젝트 생성(WSACreateEvent)
newEvent=WSACreateEvent();

// 이벤트 발생 유무 확인(WSAEventSelect)
WSAEventSelect(hClntSock, newEvent, FD_READ|FD_CLOSE);

hEventArray[sockTotal]=newEvent;
hSockArray[sockTotal]=hClntSock;
sockTotal++;
printf("새로 연결된 소켓의 핸들 %d \n", hClntSock);
}

// 데이터 전송해올 경우.
if(netEvents.lNetworkEvents & FD_READ) 
{
if(netEvents.iErrorCode[FD_READ_BIT] != 0)
{
puts("Read Error");
break;
}

//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//
// 서버 작업은 여기서 다하겠지..
//

// 데이터를 받음 (message에 받은 데이터를 담음)
strLen=recv(hSockArray[index-WSA_WAIT_EVENT_0],
message, sizeof(message), 0);
// 데이터 끝에 널값 입력
message[strLen]=0;
// 에코(데이터를준 클라이언트에 다시 데이터쏘기)
send(hSockArray[index-WSA_WAIT_EVENT_0], 
message, strLen,0);
// 예의상 화면에도 한번 보여줘야지
cout<<message;

//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
}


// 연결 종료 요청의 경우.
if(netEvents.lNetworkEvents & FD_CLOSE)
{
if(netEvents.iErrorCode[FD_CLOSE_BIT] != 0)
{
puts("Close Error");
break;
}
WSACloseEvent(hEventArray[index]);
// 소켓 종류
closesocket(hSockArray[index]);
printf("종료 된 소켓의 핸들 %d \n", hSockArray[index]);

sockTotal--;
// 배열 정리.
CompressSockets(hSockArray, index, sockTotal);
CompressEvents(hEventArray, index, sockTotal);
}

}//else
}//for
}//while

  
  
// 할당 받은 리소스 반환.
WSACleanup();
return 0;
}

/************************************
/* 
/* CompressSockets
/*
*/
void socketServer::CompressSockets(SOCKET* hSockArray, int omitIndex, int total)
{
int i;
for(i=omitIndex; i<total; i++)
{
hSockArray[i]=hSockArray[i+1];
}
}

/************************************
/* 
/* CompressEvents
/*
*/
void socketServer::CompressEvents(WSAEVENT* hEventArray, int omitIndex, int total)
{
int i;

for(i=omitIndex; i<total; i++)
{
hEventArray[i]=hEventArray[i+1];
}
}

/************************************
/* 
/* ErrorHandling
/*
*/
void socketServer::ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}




// 한번 실행해보는 메인함수!!
/************************************
/* 
/* main
/*
*/
int main(){

// 서버 인스턴트
socketServer server;
// 서버시작
server.StartServer();
}
저작자 표시
posted by hengki
2009/06/09 12:23 Hengki's Program/ETC
 AVR 내가 이놈을 건드리게 될지는 나조차 몰랐다. 어찌 하다 참여하게된 동아리 프로젝트에 sw나봐줄까 하다가(할줄 아는건 프로그래밍뿐..)   어찌 어찌 하다 hw 제작까지 하게 되었다. 이 포스팅을보게면 최소한 LED에 불을 켤수 있을거임.. -_- (못켜면 당신 두뇌 탓을..)

사용한것들
- ATmeaga128 보드 (ATMK-128V1 개발 KIT - Atmega128,uC/os-II RTOS)
- isp 
- 기타 잡다한 것들.. 


1. AV는 알겠는데 AVR은 모르겠더라..
 - 이놈도 컴퓨터인데. 어떻게 써먹어야할지 참으로 난감.. 어떻게 시작해야 할지 일단 자료 수집을 하다가 당근이 카페를 알게되고 디지털 논리회로, 컴퓨터 구조 배우던생각도 나고 해서 어 되네 라는 분위기? 머 여튼 LED에 불이 라도 켜보자 라는 의도로 삽질이 시작 되었다.. 두둥


2. 첫번째 삽질..일단 해보자
 - 첫날 후배들을 보니 보드에 프로그램을 집어 넣어야 한다는 것이다. 근데 접속이 안된다규! 절규! 그런거규! - _- 우리가 가지고 있던 보드는 꽤고가에(20만원가량)  이리저리 기능도 많은 지원 받아서 산 비싼 보드라는 사실.. 그래서 그런지 하나도 조심 스럽지 않고..(불길한 미래가 보인다.)  나는 아는것이 하나도 없고 후배들도 그닥 인거 같고. 일단 가지고 있는 부품을 적당한 구멍에 끼워서 연결을 시도 해 보았다. 나름 컴퓨터 공학전공인데 컴퓨터와 연결할수 있는 통로는 COM(RS232)포트와 LPT포트를 혹은 USB를 사용한다는것 정도는 알았기에 삽질은 반절로 줄어든 상테. 가장 쉽게 연결될거 같은 COM PORT로 시도! 연결이 안된다...(털썩) 작년에 이걸로 연결했어요.. 하며 나타난 LPT포트(프린트케이블) 안된다.. 머가 문제지??!! 한 5시간 개고생.. 그리고 포기... 우리 학습이 필요해..근성으론 역부족이라는..

2-1. 학습을 하자.
 - 내 머리좀 따줘~따줘~ 늦은 밤까지 동방에서 개고생!! 크리 터진후 집으로 보드와 잡다한 전선들을 가지고 와서 이리 저리 돌려보고 끼워보고 별짓 다해봤지만.. 아까와 마찬가지.. 뭐가 문제일까? 처음부터 다시 보게 되었다. 1차 구입한 웹 사이트를 뚤어 져라 관찰 그리고 메뉴얼을 뚤어질듯 메뉴얼 독파!! 그리고 결론. 


멀 또사라는건가``; ISP는 머지? 웹서핑 -_-) 아.. ISP라는게 따로 있어서 그걸로 프로그램을 집어 넣어주는구나 -_-) 직접 제작해도 된다고도 하지만.. 쌩초보는 닥치고 사는거닷 -_-); ISP 배송될때까지 기다려주는 센스!!

※ AVR?

AVR의 ISP(In system programing)의 기능은 일단 가장 중요한 것은 Flash에 사용자가 작성한  Code를 
Write해주는게 가장 중요한 기능이겠죠. 실제 C언어로 코딩을 하게 되면 Hex파일과 어셈으로 변환되고 Flash의 App 영역에 들어가게 됩니다. (Boot  영역이 아닌것에 주의 -> 물론 부트로더도 사용자가 변경하여 올릴 수 있죠) AVR에서 ISP 기능은 SPI통신 방식을 이용하게 되는데요.. SPI는 보통 Chip끼리의 1:1 통신에서 사용되는 방식입니다.
MISO(Master Input Slave Output)
MOSI(Master Output Slave Input)
SCK(동기 클럭신호)
SS(Select Slave)
이렇게 4개의 핀을 통해 통신을 하게 되는 방식이지요. ISP에서는 /SS 대신에 /Reset을 연결하여 Write를 할때 Reset이 걸린 상태에서 들어가게 됩니다. 

출처 :네이버 지식인

2-3. 정리하면
- 보드가 딸려있던 COM(RS232)포트로 프로그램 집어 넣을려다 포기 -_-); JTEC 포트로 병렬 포트로 연결하려다가 실패..작년 프로젝트에선 10핀짜리 ISP 였는데.. 올해온 보드는 6핀짜리였다는... 그것도 고장났는지.. 핀배열 마춰가면서 이리저리 해봐도... 좌절... 결국엔 6핀이 지원되는 ISP를 장바구니에 담았다는...


3. 길다면 이것만..
- 쓰다 보니 길어졌네요;; 이 포스팅은 다 필요 없고 -_-); 보드에 ISP라는 포트가 있습니다. 거기에 ISP보드를 연결해서 프로그램을 넣어야 하는데요. 종류에는 세종류가 있더군요. COM, LPT, USB 포트 USB는 비싸고 그냥 COM 포트를 주문 했습니다. 주문하고 보니 걍 USB 살걸 하는 생각도 드네요; USB는 따로 드라이버를 설치해서 COM포트로 인식 해서 사용한다고 하고, LPT는 제가 사용하는 AVRSTUDIO에서 인식을 못하더군요; 그래서 COM포트이용!! 머 직접 제작 하시는분들도 있던데. 제가 아는 지식은 + 에서 - 로 전기가 흘러야 불이 켜진다 정도이니... 어디까지 하게 될지는 저도 모르겠네요..

4. 만약 이포스트를 보고 나도 한번 해보자 한다면..
- http://devicemart.co.kr/ 여기는 전자부품을 파틑 사이트인데요. 여기서 atmeaga128 보드와 isp 그리고 led와 빵판 세그먼트 도트 메트릭스 전선 같은걸 사서 해보셔요! C언어 제어문만 안다면 해볼만한것 같음 .. 아님말고..

최종목표 : 온습도 센서, TCP/IP 통신. 세그먼트, 도트메트릭스, DC모터, 220V릴레이제어 
저작자 표시
posted by hengki
TAG atmega128, AVR
2009/06/08 00:10 Hengki's Story

 어제부로 식구가 하나 늘었다 CRT 모니터 원래 19인치 lcd 모니터를 사용했었는데. 몇달전 쯤에 운명을 다해 버린 관계로 22" LCD 노트북 조합으로 몇달간 버텼지만... 작업하기는 약간 불편했다.. 그래서 어디서 굴러들어온 17인치 CRT모니터 볼록하고 오래되서 그런지 글자도 선명 하지 못하지만.. 나름 쓸만하다는. (하지만 조만간 내눈은 더 나빠지겠다는;;) 

 17인치라서 그런지 가로로는 못보겠고 새로로 피봇해서 사용하는데 음좀짱인듯 ㅋㅋ



CRT라서 좋은점은 항상 LCD로 작업해서 그런지 사진이나 이미지 색이 부정확했던거 같은데 CRT 요놈은 사람을 속이지 않아서 좋네 ㅎ 어디 평면으로 좀 얇은 CRT 못구하나 =ㅅ=);;


저작자 표시
posted by hengki
prev 1 2 next