플렛폼 SDK

커뮤티케이션

커뮤니케이션의 함수 일람


함수 설명
BuildCommDCB 지정한 DCB구조체에 디바이스 제어 문자열로 지정한 값을 저장한다.
BuildCommDCBAndTimeouts 디바이스 정의 문자열을 다비아스 제어 블럭 코드에 변환한 후, 디바이스 제어 블럭에 저장한다.
ClearCommBreak 지정한 통신 디바이스의 회선이 끊긴 상태를 해제하고 문자 송신을 다시 시작한다.
ClearCommError 통신 에러의 정보를 얻고 통신 디비이스의 현재 상태를 통지한다.
CommConfigDialog 드라이버가 제공하는 설정 다이얼로그 박스를 표시한다.
EscapeCommFunction 지정한 통신 디바이스에 확장 기능을 실행하도록 지시한다.
GetCommConfig 통신 디바이스의 현재 구성을 얻는다.
GetCommMask 지정한 통신 디바이스의 이벤트 마스트의 값을 얻는다.
GetCommModemStatus 모뎀의 제어 레지스터 값을 얻는다.
GetCommProperties 지정한 통신 디바이스의 통신 프로퍼티의 정보를 버퍼에 넣는다.
GetCommState 지정한 통신 디바이스의 현재의 제어 설정을 디바이스 제어 블럭(DCB구조체)에 저장한다.
GetCommTimeouts 지정한 통신 디바이스로 실행 되는 모든 읽고 쓰는 조작의 타임아웃 파라미터를 얻는다.
GetDefaultCommConfig 통신 디바이스의 초기 설정의 구성을 얻는다.
PurgeComm 지정한 통신 자원의 출력 버퍼 또는 입력 버퍼에 있는 모든 문자를 파기한다.
SetCommBreak 지정한 통신 디바이스의 문자송신을 중단하고ClearCommBreak함수가 호출 되어질때 까지 송신 회선을 절단 상태로 한다.
SetCommConfig 통신 디바이스의 현재의 구성을 설정한다.
SetCommMask 특정 통신 디바이스로 감시하는 일련의 이벤트를 설정한다.
SetCommState 디바이스 제어 블럭(DCB구조체)의 지정에 따라서 통신 디바이스를 구성한다.
SetCommTimeouts 지정한 통신 디바이스로 실행되는 모든 읽기 쓰기 조작의 타임아웃을 설정한다.
SetDefaultCommConfig 통신 디바이스의 기본 설정의 구성을 설정한다.
SetupComm 지정한 통신 디바이스의 통신 파라미터를 초기화한다.
TransmitCommChar 지정한 통신 디바이스의 출력 버퍼에 있는 미처리 데이터보다 전에 특정 문자를 송신한다.
WaitCommEvent 지정한 통신 디바이스에서 이벤트가 발생하는 것을 대기한다.
위 링크는 일본 MSDN의 설명이 링크되어 있음

http://msdn2.microsoft.com/en-us/library/aa363194.aspx

위 함수 일람의 영어 설명은 위에 사이트에 기술되어져 있음
Posted by 띠리
우선 예제만 간단한 예제 소개부터...
그냥 밑에 소스를 가지고 프로그램을 만들기만 하면 된다.
DLL만들때는 VS2005에서 만들때는
빈 프로젝트를 만들어서 소스 파일을 하나 추가해서 아래 소스를 붙여 넣는다.
메뉴의 프로젝트(P) > ??? 속성(P)...을 선택한다.
구성 속성 > 일반을 선택한뒤
프로젝트 기본값의 구성형식을 동적 라이브러리(.dll)을 선택하면 된다.

DLL 불러쓰기의 프로젝트는 그냥 Win32콘솔 응용 프로그램에서
빈 프로젝트를 만들어서 소스를 추가하면 된다.
문자 집합은 멀티바이트 문자 집합 사용을 선택하면 밑에 소스를 그대로 쓸수있다.


초간단 DLL만들기


#include <stdio.h>

#include <windows.h>


#define EXPORT extern "C" __declspec(dllexport)


// DLL을 로드한 곳에서 EXPORT한 함수명을 쓸수있게 함

EXPORT int APlusB(int nA, int nB);

EXPORT int AMinusB(int nA, int nB, int& nVal);


BOOL APIENTRY DllMain(HANDLE hModule,

                      DWORD ul_reason_for_call,

                      LPVOID lpReserved)

{

    return TRUE;

}


EXPORT int APlusB(int nA, int nB)

{

    return nA + nB;

}


EXPORT int AMinusB(int nA, int nB, int& nVal)

{

    if(nA > nB)

    {

        nVal = nA - nB;

        return TRUE;

    }

    else

        return FALSE;

}


DLL불러쓰기


#include <stdio.h>

#include <windows.h>


// DLL에서 호출할 함수의 형

typedef int (*APlusB)(int, int);

typedef int (*AMinusB)(int, int, int&);


int main()

{

    HINSTANCE    hInst;


    APlusB    fAPlusB;

    AMinusB    fAMinusB;


    // DLL 로드

    hInst = LoadLibrary("SmallDll.dll");


    if(hInst == NULL)

        return 1;


    // 호출한 함수를 맵핑

    fAPlusB = (APlusB)GetProcAddress(hInst, "APlusB");

    fAMinusB = (AMinusB)GetProcAddress(hInst, "AMinusB");


    int            nA = 700;

    int            nB = 200;

    int            nRet = 0;

    int            nRetVal = 0;


    nRet = fAPlusB(nA, nB);

    printf("%d + %d = %d\n",nA, nB, nRet);


    nRet = fAMinusB(nA, nB, nRetVal);

    if(nRet)

        printf("%d - %d = %d\n",nA, nB, nRetVal);

    else

        printf("%d < %d \n",nA, nB);


    // DLL 언로드

    FreeLibrary(hInst);


    return 0;

}



Posted by 띠리
정말 간단한 http 서버이다.
이런 것을 http 서버라 할 수 있을까정도로...
그래도 웹브라우저로 접속할 수 있으니까...


#include <stdio.h>

#include <winsock2.h>


int main()

{

    WSADATA wsaData;

    SOCKET    sockSvr;

    SOCKET    sockSS;

    int        nlen;

    struct    sockaddr_in    addrSockSvr;

    struct    sockaddr_in    addrSockclt;

    long    nRet;

    BOOL    bValid = 1;


    char    szBuf[2048];

    char    szInBuf[2048];


    // 윈속 초기화

    if(WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)

    {

        return 1;

    }


    // 소켓 만들기

    sockSvr = socket(AF_INET, SOCK_STREAM, 0);

    if(sockSvr == INVALID_SOCKET)

    {

        printf("Socket Error No : %d", WSAGetLastError());

        return 1;

    }


    // 소켓 설정

    addrSockSvr.sin_family = AF_INET;

    addrSockSvr.sin_port = htons(333);

    addrSockSvr.sin_addr.S_un.S_addr = INADDR_ANY;


    // 소켓 옵션 설정

    setsockopt(sockSvr, SOL_SOCKET, SO_REUSEADDR, (const char *)&bValid, sizeof(bValid));


    if(bind(sockSvr, (struct sockaddr *)&addrSockSvr, sizeof(addrSockSvr)) != 0)

    {

        printf("Bind Error No : %d", WSAGetLastError());

        return 1;

    }


    // TCP클라이언트로 부터 접속 요구를 대기

    if(listen(sockSvr, 5) != 0)

    {

        printf("Listen Error No : %d", WSAGetLastError());

        return 1;

    }



    // 응답용 HTTP 메세지 작성

    memset(szBuf, 0, sizeof(szBuf));

    _snprintf(szBuf, sizeof(szBuf),

                "HTTP/1.0 200 OK\r\n"

                "Content-Length: 20\r\n"

                "Content-Type: text/html\r\n"

                "\r\n"

                "초간단 HTTP 서버\\n");


    while (1) {


        // TCP클라이언트로 부터 접속 요구 받기\tab   

        nlen = sizeof(addrSockclt);

        sockSS = accept(sockSvr, (struct sockaddr *)&addrSockclt, &nlen);


        if(sockSS == INVALID_SOCKET)

        {

            printf("Accept Error No : %d", WSAGetLastError());

            return 1;

        }



        memset(szInBuf, 0, sizeof(szInBuf));

        recv(sockSS, szInBuf, sizeof(szInBuf), 0);

        // 클라이언트로 받은 요구 처리 필요(여기서는 생략)

        printf("%s", szInBuf);


        // 클라이언트에 테스트용 HTTP 메세지 송신

        send(sockSS, szBuf, (int)strlen(szBuf), 0);


        closesocket(sockSS);

    }


    // 윈속 종료

    WSACleanup();


    return 0;


}



위 소스로 실행파일을 만들어 실행 시킨 후
밑의 주소를 웹브라우저에 입력하면

http://127.0.0.1:333/ 

밑의 그림 같이 웹브라우져에 정보가 표시된다.

사용자 삽입 이미지


안써도 다 아는 이야기겠지만 실제 HTTP서버를 만들려면
앞으로 넘어야 될 산은 정말 많을꺼다. ^^;
Posted by 띠리

TCP의 서버 프로그램을 종료한 바로뒤 다시 서버를 기동하면
bind에서 에러(Address aleady in use)로 끝날 때가 있다.

TCP의 서버 프로그램을 종료하고 다시 기동시켰는데 왜 bind가 되지 않을까?
라고 생각하며 시간이 지난후 다시 기동시키면 문제업이 bind가 된다.

이 문제는 TCP 자체 사양에 의하여 일어나는 문제이다.
구체적으로는 TCP의 TIME_WAIT상태가 bind를 fail시킨다.

서버는 TCP 세션을 받은 상태에서 close하면 TIME_WAIT상태가 된다.
이때 주의해야되는 것은 TCP 서버의 TIME_WAIT가 발생하는 경우와
발생하지 않는 경우가 있다는 것이다.

TCP서버 쪽에서 close를 먼저 실행하면 TIME_WAIT상태가 발생하지만
TCP클리아언트 쪽에서는 먼저 close를 실행해도 서버 쪽에
TIME_WAIT가 발생하지 않는다.
더 구체적으로 쓴다면 클라이언트가 먼저 FIN을 송신하면 TCP서버 쪽에는
TIME_WAIT상태에 빠지지않는다.

TIME_WAIT상태는 "netstat -na" 명령을 도스창에서 쳐보면 확인할 수 있다.
TCP세션이 확립된 경우 "netstat -na"를 쳐보면 ESTABLISHED라고 표시되어진다.
TCP세션이 종료된 후 "netstat -na" 명령을 쳐보면 TIME_WAIT생태를 볼수있다.

TIME_WAIT상태는 같은 포트를 다른 프로세스가 이용하는 것을 막기 위해
TCP 규격으로 규정되어져있다.
TIME_WAIT상태의 포트와 동일한 포트를 bind하려하면 bind는 실패한다.
단 끝나버린 프로세스가 쓰고 있는 포트 번호를 바로 쓸 수 없으면 곤란함으로
TIMW_WAIT상태로 남아있는 TCP세션이 있더라도 bind할 수 있는 방법이 있다.
그 방법이 SO_REUSEADDR을 유효하게 하는 것이다.

SO_REUSEADDR를 유효하게 하는 방법은 setsockopt함수를 이용하여
소켓에 옵션을 설정할 수 있다.

#include <stdio.h>

#include <winsock2.h>


int main()

{

    WSADATA wsaData;

    SOCKET    sockSvr;

    SOCKET    sockSS;

    int        nlen;

    struct    sockaddr_in    addrSockSvr;

    struct    sockaddr_in    addrSockclt;

    BOOL    bValid = 1;


    // 윈속 초기화

    WSAStartup(MAKEWORD(2, 0), &wsaData);


    // 소켓 만들기

    sockSvr = socket(AF_INET, SOCK_STREAM, 0);


    // 소켓 설정

    addrSockSvr.sin_family = AF_INET;

    addrSockSvr.sin_port = htons(333);

    addrSockSvr.sin_addr.S_un.S_addr = INADDR_ANY;


    // 소켓 옵션 설정

    setsockopt(sockSvr,                // SOCKET

            SOL_SOCKET,                // level

            SO_REUSEADDR,            // Option

            (const char *)&bValid,    // Option Value

            sizeof(bValid));             // Option length


    bind(sockSvr, (struct sockaddr *)&addrSockSvr, sizeof(addrSockSvr));


    // TCP클라이언트로 부터 접속 요구를 대기

    listen(sockSvr, 5);


    while (1) {


        // TCP클라이언트로 부터 접속 요구 받기\tab   

        nlen = sizeof(addrSockclt);

        sockSS = accept(sockSvr, (struct sockaddr *)&addrSockclt, &nlen);


        // 문자송신

        printf("%s 로부터 접속 (포트번호:%d)\n",

                inet_ntoa(addrSockclt.sin_addr),    // IP어드레스

                ntohs(addrSockclt.sin_port));        // 포트번호


        send(sockSS, "안녕", 5, 0);


        closesocket(sockSS);

    }


    // 윈속 종료

    WSACleanup();


    return 0;


}


Posted by 띠리

서버가 클라이언트의 접속을 기다리다가 클라이언트가 접속 되었을때
어느 클라이언트가 접속 했는지 알아야 할때가 있다.

accept가 되어지면 accept함수의 두번째 파라미터에 상대방에 대한 정보가 저장되어진다.
예제는 accept한 상대방의 IP어드레스와 포트를 표시한다.
(IP어드레스는 문제없이 가져오는데 포트를 제대로 못가져온다. -.-;;; )
(왜 이상한 포트 번호가 넘어오는지 모르겠다. -.-????? )

 


#include <winsock2.h>

#include <stdio.h>


int main()

{

    WSADATA   wsaData;

    SOCKET    sockSvr;

    SOCKET    sockSS;

    int       nlen;

    struct sockaddr_in    addrSockSvr;

    struct sockaddr_in    addrSockclt;


    // 윈속 초기화

    WSAStartup(MAKEWORD(2, 0), &wsaData);


    // 소켓 만들기

    sockSvr = socket(AF_INET, SOCK_STREAM, 0);


    // 소켓 설정

    addrSockSvr.sin_family = AF_INET;

    addrSockSvr.sin_port = htons(333);

    addrSockSvr.sin_addr.S_un.S_addr = INADDR_ANY;

    bind(sockSvr, (struct sockaddr *)&addrSockSvr, sizeof(addrSockSvr));


    // TCP클라이언트로 부터 접속 요구를 대기

    listen(sockSvr, 5);


    while (1) {


        // TCP클라이언트로 부터 접속 요구 받기\tab   

        nlen = sizeof(addrSockclt);

        sockSS = accept(sockSvr, (struct sockaddr *)&addrSockclt, &nlen);


        // 문자송신

        printf("%s 로부터 접속 (포트번호:%d)\n",

                inet_ntoa(addrSockclt.sin_addr),     // IP어드레스

                ntohs(addrSockclt.sin_port));         // 포트번호


        send(sockSS, "안녕", 5, 0);


        closesocket(sockSS);

    }


    // 윈속 종료

    WSACleanup();


    return 0;

}






Posted by 띠리
실제로 프로그램을 짤때에는 에러처리를 잘해야되는 것은 두말할 것도 없을 것같다.


#include <stdio.h>

#include <winsock2.h>


int main()

{

    WSADATA wsaData;

    SOCKET    sockSvr;

    SOCKET    sockSS;

    int        nlen;

    struct    sockaddr_in    addrSockSvr;

    struct    sockaddr_in    addrSockclt;

    long    nRet;


    // 윈속 초기화

    if(WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)

    {

        return 1;

    }


    // 소켓 만들기

    sockSvr = socket(AF_INET, SOCK_STREAM, 0);

    if(sockSvr == INVALID_SOCKET)

    {

        printf("Socket Error No : %d", WSAGetLastError());

        return 1;

    }


    // 소켓 설정

    addrSockSvr.sin_family = AF_INET;

    addrSockSvr.sin_port = htons(333);

    addrSockSvr.sin_addr.S_un.S_addr = INADDR_ANY;

    if(bind(sockSvr, (struct sockaddr *)&addrSockSvr, sizeof(addrSockSvr)) != 0)

    {

        printf("Bind Error No : %d", WSAGetLastError());

        return 1;

    }


    // TCP클라이언트로 부터 접속 요구를 대기

    if(listen(sockSvr, 5) != 0)

    {

        printf("Listen Error No : %d", WSAGetLastError());

        return 1;

    }


    while (1) {


        // TCP클라이언트로 부터 접속 요구 받기\tab   

        nlen = sizeof(addrSockclt);

        sockSS = accept(sockSvr, (struct sockaddr *)&addrSockclt, &nlen);


        if(sockSS == INVALID_SOCKET)

        {

            printf("Accept Error No : %d", WSAGetLastError());

            return 1;

        }


        // 메세지 송신

        nRet = send(sockSS, "안녕", 5, 0);

        if(nRet < 1)

        {

            printf("Send Error No : %d", WSAGetLastError());

            return 1;

        }

        closesocket(sockSS);

    }


    // 윈속 종료

    WSACleanup();


    return 0;

}




Posted by 띠리
알고보니까 정말 간단한데
어떻게 하는건가 무지 해맸었다. -.-;;




#include <windows.h>


int WINAPI WinMain(HINSTANCE hInstance,

                   HINSTANCE hPreInst,

                   LPSTR lpszCmdLine,

                   int nCmdShow)

{

    // 처리할 내용


    return TRUE;

}


Posted by 띠리
태그 SDK

태스크 바의 크기를 제외한 바탕 화면의 크기를 알고 싶을 때가 있다.
그럴 때는 SystemParametersInfo 를 쓰면 된다.

#include "stdio.h"
#include "Windows.h"


void main()

{

    RECT rcData;

    SystemParametersInfo(SPI_GETWORKAREA, 0, &rcData, 0);

}

RECT구조체의 rcData에 태스크 바의 크기를 제외한 바탕 화면의 크기의 좌표를 구한다.

Posted by 띠리
태그 API, SDK

======================================================================

#include <windows.h>

#include <stdio.h>

#include <conio.h>


#define EvtName "PipeEvent"

#define PipeName "\\\\.\\pipe\\TestPipe"


HANDLE hEvent, hFile;


int main()

{

    char    szBuf[1024];

    DWORD    dwWritten;


    hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, EvtName);

    if (hEvent == NULL)

    {

        printf("이벤트 열기 실패\");

        _getch();

        return -1;

    }


    hFile = CreateFile(PipeName,

                GENERIC_WRITE,

                0,

                NULL,

                OPEN_EXISTING,

                0,

                NULL);


    if (hFile == INVALID_HANDLE_VALUE)

    {

        printf("파이프 접속 실패\");


        CloseHandle(hFile);


        _getch();

        return -2;

   }


   while (1)

   {

       printf("송신 데이터>");

       gets(szBuf);


       if (strcmp(szBuf, "quit") == 0)

       {

           SetEvent(hEvent);


           WriteFile(hFile, szBuf, (int)strlen(szBuf), &dwWritten, NULL);


           break;

       }


       SetEvent(hEvent);


       WriteFile(hFile, szBuf, (int)strlen(szBuf), &dwWritten, NULL);

   }


   if (CloseHandle(hFile))

   {

       printf("파이프 끊기\");

   }


   printf("서버부터의 이벤트 대기중\");


   WaitForSingleObject(hEvent, INFINITE);


   printf("아무 키나 누르세요\");


   _getch();


   return 0;

}


======================================================================

이것도 서버쪽과 같은 방법으로 빌드한다.

서버쪽을 먼저 실행시키고 클라이언트를 실행시켜서 클라이언트 쪽에서 데이터를 입력하고 엔터를 치면 서버쪽에서 클라이언트 쪽에서 송신한 데이터를 수신하고 클라이언트쪽에서 "quit"라고 입력하면 서버쪽이나 클라이언트 쪽 모두 종료하게 되어있다.

Posted by 띠리

윈도우가 없는 실행 파일을 만들려면 어떻게 하면 될까?
어제 좀 고민했었다.

인터넷에서 찾아봤는데 잘 안찾아졌었다.
너무 쉽고 너무 당연한거여서 인터넷에 올린 사람들이 없는가보다.
그래도 나같이 혹시 찾는 사람들이 있을까 해서 만들어본다.

윈도우가 없는 실행 파일을 만드는 법은 생각보다 쉬웠다.

새 프로젝트를 만들때 프로젝트 형식에서
다른 언어의 Visual C++를 선택해서 Win32를 선택한다.
템플릿의 Win32프로젝트를 선택해서
이름에 프로젝트 명을 쓰고 「확인」버튼을 누른다.
다시 「다음>」버튼을 누른다.
응용 프로그램 종류에서 Windows 응용 프로그램을 선택하고
□빈 프로젝트를 선택하고 「마침」버튼을 누른다.

Ctrl+Shift+A를 눌르면 새항목추가에서
C++파일을 적당한 이름을 주어 추가한다.
C++파일에 아래 소스를 붙여 넣는다.

(내 개발 환경은 지금 VS2005를 쓰고 있다.)

======================================================================

#include <windows.h>


int WINAPI WinMain(HINSTANCE hInstance,

                   HINSTANCE hPreInst,

                   LPSTR lpszCmdLine,

                   int nCmdShow)

{

    // 처리할 내용

    while(1)

    {

        Sleep(1);

    }


    return TRUE;

}


======================================================================

이렇게 하면 윈도우가 없는 프로세스를 만들 수 가 있다.

이 방법외에도 몇가지 더 있기는 한 것같다.

예를들어Win32콘솔 응용 프로그램을 선택해서 만들어도 되기는 하지만
Win32콘솔 응용 프로그램으로 실행 파일을 만들면 콘솔창이 한번 뜬다.
다른 프로세서에서 Win32콘솔 응용 프로그램을 실행시킬때 콘솔을 표시안하게 하는 법을 쓰면 되기는 하젰지만...

아니면 서비스로 만들거나 COM으로 만들 수 도 있나보다.
Posted by 띠리
BLOG main image
프로그래밍 공부하면서 써가는 개인 노트 (따라서 여기에 씌여있는 소스의 신빙성을 보장 못함 -.-;;) 이 블로그 보면서 틀린 점이 있으면 꼬옥 알려주세요. by 띠리

공지사항

카테고리

분류 전체보기 (323)
Win32 SDK 초보 (27)
통신관련 (11)
MFC TIP (20)
C/C++ TIP (10)
개발기타 (10)
링크 (2)
견물생심 (24)
이것저것 (8)
용어메모 (3)
데이터베이스 (32)
비주얼 베이직 (10)
하드웨어 (3)
C# (42)
Xcode (3)
델파이 (82)
홈페이지 (5)
MindStorm (0)
낙서 (5)
스크래치 (0)
기타 (6)
아두이노 (1)
라즈베리파이 (2)
안드로이드 (6)
파이썬 (0)
WEB (2)
Excel VBA (0)
Total : 1,005,830
Today : 17 Yesterday : 380