"IOCP 채팅"에 해당되는 글 - 1건

Post

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

IOCP window 채팅 클라이언트 소스


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

WinChatClnt.zip

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <windowsx.h>
#include <process.h>
#include <tchar.h>
#include "resource.h"
#include <string.h>
 
#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
 
</string.h></tchar.h></process.h></windowsx.h></windows.h></ws2tcpip.h></winsock2.h></stdlib.h></stdio.h>

Dialog ID : CHAT_DIALOG

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

채팅 메시지 입력 Edit ID : IDC_CHAT_ENTER 

확인 버튼 ID : IDOK


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

▲ top