Post

2018/10/04 - [Programing/Server] - IOCP window 채팅 클라이언트 소스

IOCP window 채팅 클라이언트 소스


아래는 IOCP window 채팅 클라이언트 프로젝트이다

WinChatClnt.zip

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "resource.h"
#include 

#pragma comment(lib, "ws2_32.lib")

struct SOCKDATA
{
    SOCKET hSocket;
    SOCKADDR_IN servAdr;
};

SOCKET hSocket = 0;     // 소켓. 메시지 처리에서도 사용해야되서 전역변수로 선언
HWND hMsgWnd = 0;     // 메시지 받고 나서 ui처리해야 되서 전역변수로 선언


#pragma region RegionName
#define BUF_SIZE 1024
void ErrorHandling(const char* message);
void StartServerConnect(WSADATA& wsaData, SOCKET& hSocket, SOCKADDR_IN& servAdr);       // 소켓 초기화
DWORD WINAPI ServerThreadMain(LPVOID socket);                                   // 서버와 데이터를 주고 받는 Thread

BOOL Dlg_OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam) {
    // WM_INITDIALOG: Dialog Box 초기화 코드 작성
    return (TRUE);
}

void Dlg_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify) {

    if (0 == hMsgWnd)
    {
        hMsgWnd = hWnd;
    }

    //WM_COMMAND
    switch (id) {
    case IDOK:
    {
        TCHAR buff[BUF_SIZE];
        GetDlgItemText(hWnd, IDC_CHAT_ENTER, buff, BUF_SIZE);
        char temp[BUF_SIZE];
        WideCharToMultiByte(CP_ACP, 0, buff, BUF_SIZE, temp, BUF_SIZE, NULL, NULL);
        printf("%s \n", temp);

        int len = strlen(temp);
        send(hSocket, temp, len, 0);

        memset(buff, 0, BUF_SIZE);

        // 글자 없애기
        SetDlgItemText(hWnd, IDC_CHAT_ENTER, buff);

        break;
    }
    case WM_DESTROY:
        exit(0);

        break;
    }
}

// DialogBox Procedure
INT_PTR WINAPI Dlg_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
    case WM_INITDIALOG:
        return (SetDlgMsgResult(hWnd, uMsg, HANDLE_WM_INITDIALOG((hWnd), (wParam), (lParam), (Dlg_OnInitDialog))));

    case WM_COMMAND:
        return (SetDlgMsgResult(hWnd, uMsg, HANDLE_WM_COMMAND((hWnd), (wParam), (lParam), (Dlg_OnCommand))));
    }
    return (FALSE);
}

int APIENTRY _tWinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPTSTR    lpCmdLine,
    int       nCmdShow)
{
    WSADATA wsaData;
    SOCKADDR_IN servAdr;
    
    StartServerConnect(wsaData, hSocket, servAdr);

    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);


    // DialogBox생성 함수      
    DialogBox(hInstance,
        MAKEINTRESOURCE(CHAT_DIALOG/*DialogBox ID*/),
        NULL,
        Dlg_Proc/*DialogBox Procedure*/);

    return(0);
}

DWORD WINAPI ServerThreadMain(LPVOID data)
{
    SOCKDATA* socketInfo = (SOCKDATA*)data;
    if (NULL == socketInfo)
    {
        return 0;
    }

    if (connect(socketInfo->hSocket, (SOCKADDR*)(&socketInfo->servAdr), sizeof(socketInfo->servAdr)) == SOCKET_ERROR)
    {
        DWORD dwError = GetLastError();
        ErrorHandling("connect() error!");
    }
    else
        puts("Connected...........");

    char message[BUF_SIZE];
    memset(message, 0, BUF_SIZE);
    TCHAR uniMessage[BUF_SIZE];
    memset(uniMessage, 0, BUF_SIZE * sizeof(TCHAR));
    
    int strLen = 0;
    int readLen = 0;

    while (true)
    {
        //fputs("Input message(Q to quit): ", stdout);
        //fgets(message, BUF_SIZE, stdin);
        //if (!strcmp(message, "q\n") || !strcmp(message, "Q\n"))
        //    break;

        //strLen = strlen(message);
        //send(socketInfo->hSocket, message, strLen, 0);

        readLen = 0;
        while (1)
        {
            memset(message, 0, BUF_SIZE);
            readLen += recv(socketInfo->hSocket, &message[readLen], BUF_SIZE - 1, 0);
            if (readLen >= strLen)
                break;
        }
        strLen = readLen;
        message[strLen] = 0;

        // 유니코드로 변경
        memset(uniMessage, 0, BUF_SIZE * sizeof(TCHAR));
      

        // 유니코드 변경 전 유니코드 길이 구하기
        int nUniLen = MultiByteToWideChar(CP_ACP, 0, message, strlen(message), NULL, NULL);

        MultiByteToWideChar(CP_ACP, 0, message, strLen+1, uniMessage, nUniLen);
        

        if (0 != hMsgWnd)
        {
            //SetDlgItemText(hMsgWnd, CHAT_VIEW, uniMessage);
            SendDlgItemMessage(hMsgWnd, CHAT_VIEW, LB_GETCURSEL, 0, 0);
            SendDlgItemMessage(hMsgWnd, CHAT_VIEW, LB_ADDSTRING, 0, (LPARAM)uniMessage);
        }
        strLen = 0;
        //printf("Message from server: %s", message);
    }
    
    delete socketInfo;
    closesocket(socketInfo->hSocket);
    WSACleanup();

    return 0;
}

void StartServerConnect(WSADATA& wsaData, SOCKET& hSocket, SOCKADDR_IN& servAdr)
{
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        ErrorHandling("WSAStartup() error!");
    
    hSocket = socket(PF_INET, SOCK_STREAM, 0);
    if (hSocket == INVALID_SOCKET)
        ErrorHandling("socket() error");

    memset(&servAdr, 0, sizeof(servAdr));
    servAdr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &(servAdr.sin_addr));
    servAdr.sin_port = htons(atoi("7777"));

    SOCKDATA* sockData = new SOCKDATA();
    sockData->hSocket = hSocket;
    sockData->servAdr = servAdr;

    // 서버와 통신할 thread  생성
    _beginthreadex(NULL, 0, (_beginthreadex_proc_type)ServerThreadMain, (LPVOID)sockData, 0, NULL);
}


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

#pragma endregion

Dialog ID : CHAT_DIALOG

채팅 ListView ID : CHAT_VIEW (Sort 하지말것)

채팅 메시지 입력 Edit ID : IDC_CHAT_ENTER 

확인 버튼 ID : IDOK


이전에 올린 IOCP 채팅 서버와 대응하는 클라이언트다

▲ top