본문 바로가기

프로그램언어/C++

윈도우 소켓2

논블로킹 통신

논블로킹이란 서버가 무한정 기다리지 않고 다른 일을 하다가 연결을 시도하는 신호가 도착하거나 통신 메시지가 도착하면 사용자가 정의한 윈도우 메시지를 보내는 방식이다.

 

WSAAsyncSelect() 함수 : 윈도우 메시지, 네트워크 이벤트 등록 함수

int WSAAsyncSelect(

    SOCKET         s,          // 연결된 소켓

    HWND          hWnd,    // 메시지가 발생하는 윈도우의 핸들

    unsigned int   wMsg,    // 등록될 윈도우 메시지

    long             lEvent     // 등록될 네트워크 이벤트 

);

//성공시 0을 반환, 실패시 SOCKET_ERROR 반환

//네트워크 이벤트

enum NetworkEvent

{

    FD_ACCEPT,    //클라이언트가 접속하면 윈도우 메시지가 발생

    FD_READ,       //수신이 가능하면 윈도우 메시지가 발생

    FD_WRITE,      //송신이 가능하면 윈도우 메시지가 발생

    FD_CLOSE,      //접속을 종료하면 윈도우 메시지가 발생

    FD_CONNECT,  //접속이 완료되면 윈도우 메시지가 발생

    FD_OOB          //OOB 데이터가 도착하면 윈도우 메시지가 발생

};

WSAAsyncSelect( )함수를 이용하려면 먼저 윈도우 메시지를 등록해야 한다. 이것은 사용자 정의 윈도우 메시지로, 기존 윈도우 메시지와 메시지 번호가 동일하면 안 된다. 충돌을 방지하기 위해 다음과 같이 WM_USER를 사용한다. WM_USER는 메시지 정의를 위해 사용하며 숫자 2에는 다른 정수를 넣어도 된다.

#define WM_ASYNC WM_USER+2

WM_ASYNC 는 특정 네트워크 이벤트 발생시 윈도우 메시지로 사용한다.

네트워크 이벤트

FD_ACCEPT : 클라이언트가 접속하면 발생 
FD_READ : 데이터 수신이 가능하면 발생
FD_WRITE : 데이터 송신이 가능하면 발생
FD_CLOSE : 상대가 접속을 종료하면 발생
FD_CONNECT : 접속이 완료되면 발생
FD_OOB : 통신과정에서 긴급히 전송되는OOB(out-of-band) 데이터가 도착하면 발생

 

논블로킹 단방향 통신 프로그램(서버)

#include <windows.h>

#include <TCHAR.H>

#include <stdio.h>

#define WM_ASYNC WM_USER+2

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)

{

    HWND hwnd;

    MSG msg;

    WNDCLASS WndClass;

    WndClass.style = CS_HREDRAW | CS_VREDRAW;

    WndClass.lpfnWndProc = WndProc;

    WndClass.cbClsExtra= 0;

    WndClass.cbWndExtra= 0;

    WndClass.hInstance = hInstance;

    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

    WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    WndClass.lpszMenuName = NULL;

    WndClass.lpszClassName = _T("Window Class Name");

    RegisterClass(&WndClass);

    hwnd = CreateWindow( _T("Window Class Name"), _T("Server Window"), WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL );

    ShowWindow(hwnd, nCmdShow);

    UpdateWindow(hwnd);

    while(GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return (int)msg.wParam;

}

 

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

    HDC hdc;

    PAINTSTRUCT ps;

    static WSADATA wsadata;

    static SOCKET s, cs;

    static TCHAR msg[200];

    static SOCKADDR_IN addr = { 0 }, c_addr;

    int size, msgLen;

    char buffer[100];

 

    switch (iMsg)

    { 

    case WM_CREATE:

        WSAStartup(MAKEWORD(2, 2), &wsadata);

        s = socket(AF_INET, SOCK_STREAM, 0);

        addr.sin_family = AF_INET;

        addr.sin_port = 20;

        addr.sin_addr.s_addr = inet_addr("127.0.0.1");

        bind(s,(LPSOCKADDR)&addr, sizeof(addr));

        WSAAsyncSelect(s, hwnd, WM_ASYNC, FD_ACCEPT);

        if (listen(s, 5) == -1) return 0;

        break;

    case WM_ASYNC:

        switch(lParam)

        {

        case FD_ACCEPT:

            size = sizeof(c_addr);

            cs = accept(s, (LPSOCKADDR)&c_addr, &size);

            WSAAsyncSelect(cs, hwnd, WM_ASYNC, FD_READ);

            break;

        case FD_READ:

            msgLen = recv(cs, buffer, 100, 0);

            buffer[msgLen] = NULL;

#ifdef _UNICODE

            msgLen = MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), NULL, NULL);

            MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), msg, msgLen);

            msg[msgLen] = NULL;

#else

            strcpy_s(msg, buffer);

#endif

            InvalidateRgn(hwnd, NULL, TRUE);

            break;

        default:

            break;

        }

        break;

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);

        TextOut(hdc, 0, 0, msg, (int)_tcslen(msg));

        EndPaint(hwnd, &ps);

        break;

    case WM_DESTROY:

        closesocket(s);

        WSACleanup();

        PostQuitMessage(0);

        break;

    }

    return DefWindowProc (hwnd, iMsg, wParam, lParam);

}

 

 

논블로킹 단방향 통신 프로그램(클라이언트)

#include <windows.h>

#include <TCHAR.H>

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)

{

    HWND hwnd;

     MSG msg;

    WNDCLASS WndClass;

    WndClass.style = CS_HREDRAW | CS_VREDRAW;

    WndClass.lpfnWndProc = WndProc;

    WndClass.cbClsExtra= 0;

    WndClass.cbWndExtra= 0;

    WndClass.hInstance = hInstance;

    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

    WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    WndClass.lpszMenuName = NULL;

    WndClass.lpszClassName = _T("Window Class Name");

    RegisterClass(&WndClass);

    hwnd = CreateWindow( _T("Window Class Name"), _T("Client Window"), WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL );

    ShowWindow(hwnd, nCmdShow);

    UpdateWindow(hwnd);

    while(GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return (int)msg.wParam;

}

 

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

    static WSADATA wsadata;

    static SOCKET s;

    static SOCKADDR_IN addr = { 0 };

    switch (iMsg)

    {

    case WM_CREATE:

 

        WSAStartup(MAKEWORD(2, 2), &wsadata);

        s = socket(AF_INET, SOCK_STREAM, 0);

        addr.sin_family = AF_INET;

        addr.sin_port = 20;

        addr.sin_addr.s_addr = inet_addr("127.0.0.1");

        if(connect(s, (LPSOCKADDR)&addr, sizeof(addr)) == -1) return 0;

        break;

    case WM_KEYDOWN:

        send(s, "안녕 Server!", 13, 0);

        break;

    case WM_DESTROY:

        closesocket(s);

        WSACleanup();

        PostQuitMessage(0);

        break;

    }

    return DefWindowProc(hwnd, iMsg, wParam, lParam);

}

실행결과]

 

논블로킹 양방향 통신 프로그램(서버)

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

    HDC hdc;

    PAINTSTRUCT ps;

    static WSADATA wsadata;

    static SOCKET s, cs;

    static TCHAR msg[200];

    static SOCKADDR_IN addr = { 0 }, c_addr;

    int size, msgLen;

    char buffer[100];

 

    switch (iMsg)

    {

    case WM_CREATE:

        WSAStartup(MAKEWORD(2, 2), &wsadata);

        s = socket(AF_INET, SOCK_STREAM, 0);

        addr.sin_family = AF_INET;

        addr.sin_port = 20;

        addr.sin_addr.s_addr = inet_addr("127.0.0.1");

        bind(s,(LPSOCKADDR)&addr, sizeof(addr));

        WSAAsyncSelect(s, hwnd, WM_ASYNC, FD_ACCEPT);

        if (listen(s, 5) == -1)

            return 0;

        break;

    case WM_ASYNC:

        switch(lParam)

        {

         case FD_ACCEPT:

             size = sizeof(c_addr);

             cs = accept(s, (LPSOCKADDR)&c_addr, &size);

             WSAAsyncSelect(cs, hwnd, WM_ASYNC, FD_READ);

             break;

         case FD_READ:

             msgLen = recv(cs, buffer, 100, 0);

             buffer[msgLen] = NULL;

#ifdef _UNICODE

             msgLen = MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), NULL, NULL);

             MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), msg, msgLen);

             msg[msgLen] = NULL;

#else

             strcpy_s(msg, buffer);

#endif

             InvalidateRgn(hwnd, NULL, TRUE);

             break;

        default:

            break;

        }

        break;

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);

        TextOut(hdc, 0, 0, msg, (int)_tcslen(msg));

        EndPaint(hwnd, &ps);

        break;

    case WM_KEYDOWN:

        if (cs == INVALID_SOCKET)

            break;

        send(cs, "반가워 Client!", 15, 0);

        break;

    case WM_DESTROY:

        closesocket(s);

        WSACleanup();

        PostQuitMessage(0);

        break;

    }

    return DefWindowProc(hwnd, iMsg, wParam, lParam);

}

 

 

논블로킹 양방향 통신 프로그램(클라이언트)

#define WM_ASYNC WM_USER+2

...
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam)

{

    HDC hdc;

    PAINTSTRUCT ps;

    static WSADATA wsadata;

    static SOCKET s;

    static SOCKADDR_IN addr = { 0 };

    static TCHAR msg[200];

    int msgLen;

    char buffer[100];

    switch (iMsg)

    {

    case WM_CREATE:

        WSAStartup(MAKEWORD(2,2), &wsadata);

        s = socket(AF_INET, SOCK_STREAM, 0);

        addr.sin_family = AF_INET;

        addr.sin_port = 20;

        addr.sin_addr.s_addr = inet_addr("127.0.0.1");

        WSAAsyncSelect(s, hwnd, WM_ASYNC, FD_READ);

        if(connect(s, (LPSOCKADDR)&addr, sizeof(addr)) == -1)

            return 0;

       break;

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);

        TextOut(hdc, 0,0,msg, (int)_tcslen(msg));

        EndPaint(hwnd, &ps);

        break;

    case WM_ASYNC:

        switch(lParam)

        {

        case FD_READ:

            msgLen = recv(s, buffer, 100, 0);

            buffer[msgLen] = NULL;

#ifdef _UNICODE

            msgLen = MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), NULL, NULL);

            MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), msg, msgLen);

            msg[msgLen] = NULL;

#else

            strcpy_s(msg, buffer);

#endif

            InvalidateRgn(hwnd, NULL, TRUE);

            break;

        default:

            break;

        }

        break;

    case WM_KEYDOWN:

        send(s, "안녕 Server!", 13, 0);

        break;

    case WM_DESTROY:

        closesocket(s);

        WSACleanup();

        PostQuitMessage(0);

        break;

    }

    return DefWindowProc (hwnd, iMsg, wParam, lParam);

}

 

실행결과]

 

 

채팅 프로그램 만들기(서버)

#include <windows.h>

#include <TCHAR.H>

#include <stdio.h>

#define WM_ASYNC WM_USER+2

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)

{

    HWND hwnd;

    MSG msg;

    WNDCLASS WndClass;

    WndClass.style = CS_HREDRAW | CS_VREDRAW;

    WndClass.lpfnWndProc = WndProc;

    WndClass.cbClsExtra = 0;

    WndClass.cbWndExtra = 0;

    WndClass.hInstance = hInstance;

    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

    WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    WndClass.lpszMenuName = NULL;

    WndClass.lpszClassName = _T("Window Class Name");

    RegisterClass(&WndClass);

    hwnd = CreateWindow(_T("Window Class Name"), _T("Server Window"), WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL );

    ShowWindow(hwnd, nCmdShow);

    UpdateWindow(hwnd);

    while(GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return (int)msg.wParam;

}

 

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

    HDC hdc;

    PAINTSTRUCT ps;

    static WSADATA wsadata;

    static SOCKET s, cs;

    static TCHAR msg[200];

    static char buffer[100];

    static SOCKADDR_IN addr = { 0 }, c_addr;

    static TCHAR str[100];

    static int count;

    int size, msgLen;

 

    switch (iMsg)

    {

    case WM_CREATE:

        WSAStartup(MAKEWORD(2, 2), &wsadata);

        s = socket(AF_INET, SOCK_STREAM, 0);

        addr.sin_family = AF_INET;

        addr.sin_port = 20;

        addr.sin_addr.s_addr = inet_addr("127.0.0.1");

        bind(s,(LPSOCKADDR)&addr, sizeof(addr));

        WSAAsyncSelect(s, hwnd, WM_ASYNC, FD_ACCEPT);

        if (listen(s, 5) == -1)

            return 0;

        break;

    case WM_ASYNC:

        switch(lParam)

        {

        case FD_ACCEPT:

            size = sizeof(c_addr);

            cs = accept(s, (LPSOCKADDR)&c_addr, &size);

            WSAAsyncSelect(cs, hwnd, WM_ASYNC, FD_READ);

            break;

        case FD_READ:

            msgLen = recv(cs, buffer, 100, 0);

            buffer[msgLen] = NULL;

#ifdef _UNICODE

            msgLen = MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), NULL, NULL);

            MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), msg, msgLen);

            msg[msgLen] = NULL;

#else

            strcpy_s(msg, buffer);

#endif

            InvalidateRgn(hwnd, NULL, TRUE);

            break;

        default:

            break;

        }

        break;

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);

        if (_tcscmp(msg, _T("")))

            TextOut(hdc, 0, 30, msg, (int)_tcslen(msg));

        TextOut(hdc, 0, 0, str, _tcslen(str));

        EndPaint(hwnd, &ps);

        break;

    case WM_CHAR:

        if (wParam == VK_RETURN)

            if (cs == INVALID_SOCKET)

                return 0;

            else

            {

#ifdef _UNICODE

                msgLen = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);

                WideCharToMultiByte(CP_ACP, 0, str, -1, buffer, msgLen, NULL, NULL);

#else

                strcpy_s(buffer, str);

#endif

                send(cs, (LPSTR )buffer, strlen(buffer)+1, 0);

                count = 0;

                return 0;

            }

            str[count++] = wParam;

            str[count] = NULL;

            InvalidateRgn(hwnd, NULL, TRUE);

        return 0;

    case WM_DESTROY:

        closesocket(s);

        WSACleanup();

        PostQuitMessage(0);

        break;

    }

    return DefWindowProc (hwnd, iMsg, wParam, lParam);

}

 

채팅 프로그램 만들기(클라이언트)

#include <windows.h>

#include <TCHAR.H>

#include <stdio.h>

#define WM_ASYNC WM_USER+2

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)

{

    HWND hwnd;

    MSG msg;

    WNDCLASS WndClass;

    WndClass.style = CS_HREDRAW | CS_VREDRAW;

    WndClass.lpfnWndProc = WndProc;

    WndClass.cbClsExtra = 0;

    WndClass.cbWndExtra = 0;

    WndClass.hInstance = hInstance;

    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

    WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    WndClass.lpszMenuName = NULL;

    WndClass.lpszClassName = _T("Window Class Name");

    RegisterClass(&WndClass);

    hwnd = CreateWindow(_T("Window Class Name"), _T("Server Window"), WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL );

    ShowWindow(hwnd, nCmdShow);

    UpdateWindow(hwnd);

    while(GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return (int)msg.wParam;

}

 

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

    HDC hdc;

    PAINTSTRUCT ps;

    static WSADATA wsadata;

    static SOCKET s;

    static SOCKADDR_IN addr = { 0 };

    static TCHAR msg[200];

    static TCHAR str[100];

    static char buffer[100];

    static int count;

    int msgLen;

 

    switch (iMsg)

    {

    case WM_CREATE:

        WSAStartup(MAKEWORD(2, 2), &wsadata);

        s = socket(AF_INET, SOCK_STREAM, 0);

        addr.sin_family = AF_INET;

        addr.sin_port = 20;

        addr.sin_addr.s_addr = inet_addr("127.0.0.1");

        WSAAsyncSelect(s, hwnd, WM_ASYNC, FD_READ);

        if(connect(s, (LPSOCKADDR)&addr, sizeof(addr)) == -1)

            return 0;

        break;

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);

        if (_tcscmp(msg, _T(""))) TextOut(hdc, 0, 30, msg, (int)_tcslen(msg));

        TextOut(hdc, 0,0, str,_tcslen(str));

        EndPaint(hwnd, &ps);

        break;

    case WM_ASYNC:

        switch(lParam)

        {

        case FD_READ:

            msgLen = recv(s, buffer, 100, 0);

            buffer[msgLen] = NULL;

#ifdef _UNICODE

            msgLen = MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), NULL, NULL);

            MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), msg, msgLen);

            msg[msgLen] = NULL;

#else

            strcpy_s(msg, buffer);

#endif

            InvalidateRgn(hwnd, NULL, TRUE);

            break;

        default:

            break;

        }

        break;

    case WM_CHAR:

        if (wParam == VK_RETURN)

            if (s == INVALID_SOCKET)

                return 0;

            else

            {

#ifdef _UNICODE

                msgLen = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);

                WideCharToMultiByte(CP_ACP, 0, str, -1, buffer, msgLen, NULL, NULL);

#else

                strcpy_s(buffer, str);

                msgLen = strlen(buffer);

#endif

                send(s, (LPSTR )buffer, msgLen+1, 0);

                count = 0;

                return 0;

            }

        str[count++] = wParam;

        str[count] = NULL;

        InvalidateRgn(hwnd, NULL, TRUE);

        return 0;

    case WM_DESTROY:

        closesocket(s);

        WSACleanup();

        PostQuitMessage(0);

        break;

    } 

    return DefWindowProc(hwnd, iMsg, wParam, lParam);

}

 

 

한줄 채팅 프로그램 만들기(서버)

#include <windows.h>

#include <TCHAR.H>

#include <stdio.h>

#define WM_ASYNC WM_USER+2

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)

{

    HWND hwnd;

    MSG msg;

    WNDCLASS WndClass;

    WndClass.style = CS_HREDRAW | CS_VREDRAW;

    WndClass.lpfnWndProc = WndProc;

    WndClass.cbClsExtra = 0;

    WndClass.cbWndExtra = 0;

    WndClass.hInstance = hInstance;

    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

    WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    WndClass.lpszMenuName = NULL;

    WndClass.lpszClassName = _T("Window Class Name");

    RegisterClass(&WndClass);

    hwnd = CreateWindow(_T("Window Class Name"), _T("Server Window"), WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, nCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return (int)msg.wParam;

}

 

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

    HDC hdc;

    PAINTSTRUCT ps;

    static WSADATA wsadata;

    static SOCKET s, cs;

    static TCHAR msg[200];

    static char buffer[100];

    static SOCKADDR_IN addr = { 0 }, c_addr;

    static TCHAR str[100];

    static int count;

    int size, msgLen;

 

    switch (iMsg)

    {

    case WM_CREATE:

        WSAStartup(MAKEWORD(2, 2), &wsadata);

        s = socket(AF_INET, SOCK_STREAM, 0);

        addr.sin_family = AF_INET;

        addr.sin_port = 20;

        addr.sin_addr.s_addr = inet_addr("127.0.0.1");

        bind(s, (LPSOCKADDR)&addr, sizeof(addr));

        WSAAsyncSelect(s, hwnd, WM_ASYNC, FD_ACCEPT);

        if (listen(s, 5) == -1)

            return 0;

        break;

    case WM_ASYNC:

        switch (lParam)

        {

        case FD_ACCEPT:

            size = sizeof(c_addr);

            cs = accept(s, (LPSOCKADDR)&c_addr, &size);

            WSAAsyncSelect(cs, hwnd, WM_ASYNC, FD_READ);

            break;

        case FD_READ:

            msgLen = recv(cs, buffer, 100, 0);

            buffer[msgLen] = NULL;

#ifdef _UNICODE

            msgLen = MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), NULL, NULL);

            MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), msg, msgLen);

            msg[msgLen] = NULL;

#else

            strcpy_s(msg, buffer);

#endif

            InvalidateRgn(hwnd, NULL, TRUE);

            break;

        default:

            break;

        }

        break;

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);

        if (_tcscmp(msg, _T("")))

            TextOut(hdc, 0, 30, msg, (int)_tcslen(msg));

        TextOut(hdc, 0, 0, str, _tcslen(str));

        EndPaint(hwnd, &ps);

        break;

    case WM_CHAR:

        if (wParam == VK_RETURN)

            if (cs == INVALID_SOCKET)

                return 0;

        else

        {

#ifdef _UNICODE

            msgLen = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);

            WideCharToMultiByte(CP_ACP, 0, str, -1, buffer, msgLen, NULL, NULL);

#else

            strcpy_s(buffer, str);

#endif

            send(cs, (LPSTR)buffer, strlen(buffer) + 1, 0);

            count = 0;

            return 0;

        }

        str[count++] = wParam;

        str[count] = NULL;

        InvalidateRgn(hwnd, NULL, TRUE);

        return 0;

    case WM_DESTROY:

        closesocket(s);

        WSACleanup();

        PostQuitMessage(0);

        break;

    }

    return DefWindowProc(hwnd, iMsg, wParam, lParam);

}

한줄 채팅 프로그램 만들기(클라이언트)

#include <windows.h>

#include <TCHAR.H>

#define WM_ASYNC WM_USER+2

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)

{

    HWND hwnd;

    MSG msg;

    WNDCLASS WndClass;

    WndClass.style = CS_HREDRAW | CS_VREDRAW;

    WndClass.lpfnWndProc = WndProc;

    WndClass.cbClsExtra = 0;

    WndClass.cbWndExtra = 0;

    WndClass.hInstance = hInstance;

    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

    WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    WndClass.lpszMenuName = NULL;

    WndClass.lpszClassName = _T("Window Class Name");

    RegisterClass(&WndClass);

    hwnd = CreateWindow(_T("Window Class Name"), _T("Client Window"), WS_OVERLAPPEDWINDOW,

         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, nCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return (int)msg.wParam;

}

 

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

    HDC hdc;

    PAINTSTRUCT ps;

    static WSADATA wsadata;

    static SOCKET s;

    static SOCKADDR_IN addr = { 0 };

    static TCHAR msg[200];

    static TCHAR str[100];

    static char buffer[100];

    static int count;

    int msgLen;

 

    switch (iMsg)

    {

    case WM_CREATE:

        WSAStartup(MAKEWORD(2, 2), &wsadata);

        s = socket(AF_INET, SOCK_STREAM, 0);

        addr.sin_family = AF_INET;

        addr.sin_port = 20;

        addr.sin_addr.s_addr = inet_addr("127.0.0.1");

        WSAAsyncSelect(s, hwnd, WM_ASYNC, FD_READ);

        if (connect(s, (LPSOCKADDR)&addr, sizeof(addr)) == -1)

            return 0;

        break;

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);

        if (_tcscmp(msg, _T(""))) TextOut(hdc, 0, 30, msg, (int)_tcslen(msg));

        TextOut(hdc, 0, 0, str, _tcslen(str));

        EndPaint(hwnd, &ps);

        break;

    case WM_ASYNC:

        switch (lParam)

        {

        case FD_READ:

            msgLen = recv(s, buffer, 100, 0);

            buffer[msgLen] = NULL;

#ifdef _UNICODE

            msgLen = MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), NULL, NULL);

            MultiByteToWideChar(CP_ACP, 0, buffer, strlen(buffer), msg, msgLen);

            msg[msgLen] = NULL;

#else

            strcpy_s(msg, buffer);

#endif

            InvalidateRgn(hwnd, NULL, TRUE);

            break;

        default:

            break;

        }

        break;

    case WM_CHAR:

        if (wParam == VK_RETURN)

            if (s == INVALID_SOCKET)

                return 0;

         else

        {

#ifdef _UNICODE

            msgLen = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);

            WideCharToMultiByte(CP_ACP, 0, str, -1, buffer, msgLen, NULL, NULL);

#else

            strcpy_s(buffer, str);

            msgLen = strlen(buffer);

#endif

            send(s, (LPSTR)buffer, msgLen + 1, 0);

            count = 0;

            return 0;

        }

        str[count++] = wParam;

        str[count] = NULL;

        InvalidateRgn(hwnd, NULL, TRUE);

        return 0;

    case WM_DESTROY:

        closesocket(s);

        WSACleanup();

        PostQuitMessage(0);

        break;

    }

    return DefWindowProc(hwnd, iMsg, wParam, lParam);

}

실행 결과]

 

'프로그램언어 > C++' 카테고리의 다른 글

윈도우 프로그램기초예제  (0) 2021.06.08
스레드  (0) 2021.01.14
윈도우 소켓1  (0) 2021.01.12
파일 입출력2  (0) 2021.01.11
파일 입출력1  (0) 2021.01.05