Editor, Button, List 등을 쉽게 제작할 수 있음
LRESULT Sample::MsgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
// edit, button, listbox같이 Win API에서 미리 정의되어 있는 control을 통해 쉽고 빠르게 제작 가능
// RegisterClass()를 통하 마찬가지로 User가 정의한 Control도 등록, 생성 가능
// HMENU값을 통해 Event를 발생시킨 객체 확인
CreateWindow(L"edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 500, 10, 200, 25, hWnd, (HMENU)1000, m_hInstance, NULL);
CreateWindow(L"button", L"Send", WS_CHILD | WS_VISIBLE | WS_BORDER | BS_PUSHBUTTON, 700, 10, 50, 25, hWnd, (HMENU)1001, m_hInstance, NULL);
CreateWindow(L"listbox", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | WS_HSCROLL | WS_VSCROLL, 0, 0, 500, 600, hWnd, (HMENU)1002, m_hInstance, NULL);
}break;
case WM_COMMAND:
{
// HMENU로 등록한 객체 확인
switch (LOWORD(wParam))
{
case 1001:
{
WCHAR szBuffer[255] = L"";
// Control에 저장된 Text Buffer로 반환
GetWindowText(m_hEdit, szBuffer, 255);
}break;
}
}break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
만약 DirectX를 사용한다면 위에서 사용한 editor, button, listbox같은 기능을 모두 직접 구현해야 함(DirectX에서 화면을 초기화시키는 것 때문으로 짐작됨)
WinAPI와 socket을 함께 사용한다면 Include 순서를 지켜야 함
#include <winsock2.h>
#include <windows.h>
일반적인 가변인자의 사용법
일반적으로 가변인자는 시작할 때 인자의 개수를 매개변수로 넘기던가, 마지막 인자로 끝임을 전달해야 하는데, _vsntprintf()함수의 경우 그런 절차 없이 문자열의 format만 전달하는 방식으로 매개변수가 끝날 시점을 지정
문자열의 format이 결정되어 있다면 가변인자로 넘어올 각 매개변수의 크기와 개수가 결정되므로 상당히 흥미로운 접근법인듯
Socket의 RW Buffer는 packet 단위로 송수신을 보장하지 않음
가장 쉬운 해결법은 packet의 크기를 담은 Header를 포함하여 전송한 후, Header-Content단위로 분리해서 Buffer로부터 읽어오는 방법
그러나 일반적으로 물리적인 거리가 멀어질수록 CPU time에서 많은 시간을 요구한다는 점을 감안해볼 때 NIC에서 Ram으로 데이터를 읽어오는 시간 역시 많은 CPU time을 요구할 것임을 짐작할 수 있음
또한, NIC이 바로 Ram으로 올린다 하더라도 Socket Buffer에서 User Buffer로 데이터를 옮기는 시간 역시 L3 Cache보다 먼 Ram사이에서 데이터가 전송되는 것이므로 마찬가지로 많은 CPU time을 요구할 것임
이러한 성능 저하를 해결하기 위해 Socket Buffer에 저장된 모든 데이터를 한번에 읽어온 후 Packet 단위로 분리, Header-Content로 분리, 불완전 전송된 Packet에 대한 저장 같은 작업을 할 수 있는 공간을 Packet Pool이라 함
Client의 경우 connect되는 socket의 개수가 많지 않아 굳이 절실하게 요구되지는 않지만, Server의 경우 다수의 사람이 연결된다면 구현하는 것이 좋음
Multi Thread, Non-Blocking을 사용하지 않고도 Blocking하지 않게 socket 통신을 하는 방법
Blocking 함수지만 timeout이 존재하므로 빠져나올 수 있음
Select, SWASyncSelect 등이 있는데 Winsock에서만 지원하는 듯
최대 64개 socket만 지원하므로 client에서 사용한다면 큰 문제는 없을 듯
중요한건 Kernel에서 Socket의 송수신 완료 여부를 점검하며 Event driven하게 작동한다는 점
int iRet = WSAAsyncSelect(m_Sock, g_hWnd,
NETWORK_MSG, // User define custom message
FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE); // 발생시키고자 하는 event
LRESULT Sample::MsgProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
// user 가 정의한 Custom Message
// #define Custom_Msg WM_USER + n
case NETWORK_MSG :
{
if (WSAGETSELECTERROR(lParam) != 0)
{
PostQuitMessage(0);
break;
}
WORD dwSelect = WSAGETSELECTEVENT(lParam);
switch (dwSelect)
{
// Socket Descript set에 등록된 socket 중 발생한 event의 종류
case FD_CONNECT:
{
int t = 0;
}break;
case FD_READ:
{
RecvThread();
}break;
case FD_WRITE:
{
int t = 0;
}break;
case FD_CLOSE:
{
int t = 0;
}break;
}
}break;
}