Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
11
Server/GashServer/GashServer.cpp
Normal file
11
Server/GashServer/GashServer.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
// GashServer.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
20
Server/GashServer/GashServer.sln
Normal file
20
Server/GashServer/GashServer.sln
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GashServer", "GashServer.vcproj", "{0EDC1CC1-AA80-449F-9F70-ACD6B1EB9637}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{0EDC1CC1-AA80-449F-9F70-ACD6B1EB9637}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{0EDC1CC1-AA80-449F-9F70-ACD6B1EB9637}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{0EDC1CC1-AA80-449F-9F70-ACD6B1EB9637}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{0EDC1CC1-AA80-449F-9F70-ACD6B1EB9637}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
BIN
Server/GashServer/GashServer.suo
Normal file
BIN
Server/GashServer/GashServer.suo
Normal file
Binary file not shown.
225
Server/GashServer/GashServer.vcproj
Normal file
225
Server/GashServer/GashServer.vcproj
Normal file
@@ -0,0 +1,225 @@
|
||||
<?xml version="1.0" encoding="ks_c_5601-1987"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="GashServer"
|
||||
ProjectGUID="{0EDC1CC1-AA80-449F-9F70-ACD6B1EB9637}"
|
||||
RootNamespace="GashServer"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="소스 파일"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\GashServer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\IOBuffer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\NetString.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="헤더 파일"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\IOBuffer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\NetString.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="리소스 파일"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
228
Server/GashServer/IOBuffer.cpp
Normal file
228
Server/GashServer/IOBuffer.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
// IOBuffer.cpp: implementation of the CIOBuffer class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#include "stdafx.h"
|
||||
#include "IOBuffer.h"
|
||||
#include <string.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CIOBuffer::CIOBuffer()
|
||||
{
|
||||
// Head는 읽을 버퍼의 시작위치.
|
||||
// Tail은 사용되어진 버퍼의 끝.
|
||||
m_iHead = m_iTail = 0;
|
||||
|
||||
// 생성한 버퍼의 사이즈
|
||||
m_iBufSize = 0;
|
||||
// 생성한 버퍼의 포인터.
|
||||
m_cBuf = NULL;
|
||||
|
||||
// 사용된 버퍼의 사이즈 이값이 음수면 Over Flow..
|
||||
m_iBuffered = 0;
|
||||
}
|
||||
|
||||
CIOBuffer::~CIOBuffer()
|
||||
{
|
||||
DeleteIOBuf();
|
||||
}
|
||||
|
||||
void CIOBuffer::InitIOBuf()
|
||||
{
|
||||
m_iHead = m_iTail = 0;
|
||||
m_iBuffered = 0;
|
||||
|
||||
if(m_cBuf)
|
||||
memset(m_cBuf, 0, sizeof(m_cBuf));
|
||||
}
|
||||
|
||||
void CIOBuffer::NewIOBuf(int BufSize)
|
||||
{
|
||||
if(BufSize <= 0)
|
||||
BufSize = IOBUF_DEF_SIZE;
|
||||
|
||||
m_cBuf = new char[BufSize];
|
||||
if(m_cBuf == NULL)
|
||||
{
|
||||
// throw "CIOBuffer::NewIOBuf : Memory allocation failure!";
|
||||
return;
|
||||
}
|
||||
|
||||
m_iBufSize = BufSize;
|
||||
|
||||
InitIOBuf();
|
||||
}
|
||||
|
||||
void CIOBuffer::DeleteIOBuf()
|
||||
{
|
||||
if(m_cBuf)
|
||||
{
|
||||
delete []m_cBuf;
|
||||
m_cBuf = NULL;
|
||||
}
|
||||
m_iBufSize = 0;
|
||||
m_iHead = m_iTail = 0;
|
||||
m_iBuffered = 0;
|
||||
}
|
||||
|
||||
// Size 만큼 Buffer의 내용을 쓴다.
|
||||
int CIOBuffer::Append(char* Buffer, int Size)
|
||||
{
|
||||
// 오버플로우가 된다.
|
||||
if(m_iBuffered + Size >= m_iBufSize)
|
||||
{
|
||||
// throw "CIOBuffer::Append : Buffer overflow";
|
||||
return -1;
|
||||
}
|
||||
|
||||
int aSize = 0;
|
||||
int Added = 0;
|
||||
|
||||
// 모든 Size를 추가할때까지 처리한다.
|
||||
while(Size > 0)
|
||||
{
|
||||
if(Size > m_iBufSize-m_iTail)
|
||||
aSize = m_iBufSize-m_iTail;
|
||||
else aSize = Size;
|
||||
|
||||
if(aSize)
|
||||
{
|
||||
memcpy(m_cBuf+m_iTail, Buffer, aSize);
|
||||
|
||||
Added += aSize;
|
||||
Size -= aSize;
|
||||
Buffer += aSize;
|
||||
m_iTail += aSize;
|
||||
if(m_iTail >= m_iBufSize)
|
||||
m_iTail -= m_iBufSize;
|
||||
}
|
||||
}
|
||||
|
||||
CalcBuffered();
|
||||
|
||||
return Added;
|
||||
}
|
||||
|
||||
// Size만큼 데이타를 읽어 Buffer에 쓴다.
|
||||
int CIOBuffer::GetData(char* Buffer, int Size)
|
||||
{
|
||||
// 써있는 데이타 보다 많이 읽으면 써있는 데이타만 읽게 한다.
|
||||
if(GetBufferUsed() < Size)
|
||||
Size = GetBufferUsed();
|
||||
|
||||
if(Size <= 0)
|
||||
return 0;
|
||||
|
||||
// 잘려있으면. 처리한다.
|
||||
if(m_iHead+Size >= m_iBufSize)
|
||||
{
|
||||
// 여기에 지금 버그가 있다.
|
||||
int Size1 = m_iBufSize - m_iHead;
|
||||
memcpy(Buffer, m_cBuf+m_iHead, Size1);
|
||||
memcpy(Buffer+Size1, m_cBuf, Size-Size1);
|
||||
}
|
||||
else // 안잘려 있으면.
|
||||
{
|
||||
memcpy(Buffer, m_cBuf+m_iHead, Size);
|
||||
}
|
||||
|
||||
m_iHead += Size;
|
||||
if(m_iHead >= m_iBufSize)
|
||||
m_iHead -= m_iBufSize;
|
||||
|
||||
CalcBuffered();
|
||||
return Size;
|
||||
}
|
||||
|
||||
int CIOBuffer::CheckData(int Size)
|
||||
{
|
||||
// 써있는 데이타 보다 많이 읽으면 써있는 데이타만 읽게 한다.
|
||||
if(GetBufferUsed() < Size)
|
||||
Size = GetBufferUsed();
|
||||
|
||||
if(Size <= 0)
|
||||
return 0;
|
||||
|
||||
m_iHead += Size;
|
||||
if(m_iHead >= m_iBufSize)
|
||||
m_iHead -= m_iBufSize;
|
||||
|
||||
CalcBuffered();
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
void CIOBuffer::CalcBuffered()
|
||||
{
|
||||
if(m_iHead > m_iTail)
|
||||
m_iBuffered = m_iBufSize - m_iHead + m_iTail;
|
||||
else
|
||||
m_iBuffered = m_iTail-m_iHead;
|
||||
}
|
||||
|
||||
|
||||
CPacketIOBuffer::CPacketIOBuffer()
|
||||
{
|
||||
// 초기화.
|
||||
CIOBuffer::CIOBuffer();
|
||||
}
|
||||
|
||||
CPacketIOBuffer::~CPacketIOBuffer()
|
||||
{
|
||||
DeleteIOBuf();
|
||||
}
|
||||
|
||||
void CPacketIOBuffer::Lock()
|
||||
{
|
||||
LockHead = GetHead();
|
||||
}
|
||||
|
||||
void CPacketIOBuffer::UnLock()
|
||||
{
|
||||
SetHead(LockHead);
|
||||
}
|
||||
|
||||
int CPacketIOBuffer::GetPacket(char* Packet)
|
||||
{
|
||||
if(m_iHead == m_iTail)
|
||||
return 0;
|
||||
|
||||
memset(Packet, 0, MAX_PACKETSIZE);
|
||||
|
||||
int Size = 0;
|
||||
int OldHead = GetHead();
|
||||
|
||||
char End[3] = "\r\n";
|
||||
|
||||
for(int i = 0; i < MAX_PACKETSIZE; ++i)
|
||||
{
|
||||
// 삽입
|
||||
Packet[i] = m_cBuf[m_iHead];
|
||||
|
||||
m_iHead++;
|
||||
|
||||
if(m_iHead+1 > m_iBufSize)
|
||||
m_iHead = 0;
|
||||
|
||||
if(m_iHead == m_iTail)
|
||||
break;
|
||||
|
||||
if(i < 1)
|
||||
continue;
|
||||
|
||||
if(strcmp(&Packet[i-1], End)==0)
|
||||
break;
|
||||
}
|
||||
|
||||
Size = (int)strlen(Packet);
|
||||
if(Size == 0)
|
||||
{
|
||||
SetHead(OldHead);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CalcBuffered();
|
||||
return Size;
|
||||
}
|
||||
85
Server/GashServer/IOBuffer.h
Normal file
85
Server/GashServer/IOBuffer.h
Normal file
@@ -0,0 +1,85 @@
|
||||
// IOBuffer.h: interface for the CIOBuffer class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
/*****************************************************************************
|
||||
I/O Buffering 을 위한 클래스. Sock을 이용해 패킷을 주고 받을때 패킷이
|
||||
합쳐오거나 분할되어 올때 그 패킷을 관리 및 처리할때 사용된다.(IOBuffer을
|
||||
상속받은 PacektIOBuffer 클래스로 처리하게..
|
||||
|
||||
기본적으로 PacketBuffer에 저장되는 스트링(?)의 형식은 다음과 같다.
|
||||
-------------------------------------------
|
||||
| Header(4Byte-PACKET_HEADSIZE) | StringData (Header Size) |
|
||||
-------------------------------------------
|
||||
IOBuffer클래스는 위의 패킷을 하나의 배열에 순차적으로 넣어 그 패킷을
|
||||
관리한다. 2Byte는 65535까지의 길이를 처리한다.
|
||||
*****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
#define MAX_PACKETSIZE 512
|
||||
#define IOBUF_DEF_SIZE MAX_PACKETSIZE*10 // IOBuffer의 기본크기 패킷 1024개만큼 처리가능
|
||||
|
||||
class CIOBuffer
|
||||
{
|
||||
protected:
|
||||
// Head는 읽을 버퍼의 시작위치.
|
||||
// Tail은 사용되어진 버퍼의 끝.
|
||||
int m_iHead,m_iTail;
|
||||
// 생성한 버퍼의 사이즈
|
||||
int m_iBufSize;
|
||||
// 생성한 버퍼의 포인터.
|
||||
char* m_cBuf;
|
||||
|
||||
// 사용된 버퍼의 사이즈 이값이 음수면 Over Flow..
|
||||
int m_iBuffered;
|
||||
|
||||
public:
|
||||
// 사용된 버퍼의 크기 구하기.
|
||||
void CalcBuffered();
|
||||
|
||||
// 기타 inline
|
||||
inline char* GetBuffer() { return m_cBuf; }
|
||||
inline void SetHead(int Head) { m_iHead = Head; CalcBuffered(); }
|
||||
inline int GetHead() { return m_iHead; }
|
||||
inline void SetTail(int Tail) { m_iTail = Tail; }
|
||||
inline int GetTail() { return m_iTail; }
|
||||
inline int GetBufSize() { return m_iBufSize; }
|
||||
// 사용중인 버퍼의 양
|
||||
inline int GetBufferUsed() { return m_iBuffered; }
|
||||
// 비어있는 버퍼의 양
|
||||
inline int GetEmptyBuffer() { return m_iBufSize - m_iBuffered; }
|
||||
|
||||
void InitIOBuf();
|
||||
|
||||
// 추가한다.
|
||||
int Append(char* Buffer, int Size);
|
||||
// 가져온다.
|
||||
int GetData(char* Buffer, int Size);
|
||||
// 체크한다
|
||||
int CheckData(int Size);
|
||||
|
||||
void NewIOBuf(int BufSize);
|
||||
void DeleteIOBuf();
|
||||
|
||||
|
||||
CIOBuffer();
|
||||
virtual ~CIOBuffer();
|
||||
};
|
||||
|
||||
class CPacketIOBuffer : public CIOBuffer
|
||||
{
|
||||
int LockHead;
|
||||
public:
|
||||
void Lock();
|
||||
void UnLock();
|
||||
|
||||
// 한개분량의 패킷을 얻어온다.
|
||||
int GetPacket(char* Packet);
|
||||
|
||||
CPacketIOBuffer();
|
||||
virtual ~CPacketIOBuffer();
|
||||
};
|
||||
471
Server/GashServer/NetString.cpp
Normal file
471
Server/GashServer/NetString.cpp
Normal file
@@ -0,0 +1,471 @@
|
||||
#include "stdafx.h"
|
||||
#include "NetString.h"
|
||||
|
||||
CNetString::CNetString(void)
|
||||
{
|
||||
m_iIndex = 0;
|
||||
m_hWnd = NULL; // 부모 윈도우 핸들
|
||||
|
||||
m_hSocket = NULL; // 클라이언트 소켓
|
||||
m_nPort = 0; // 포트
|
||||
ZeroMemory(m_strIPAddr, sizeof(char)*20); // Server IP저장
|
||||
|
||||
m_bConnect = FALSE; // 접속 상태 플래그
|
||||
m_bClose = FALSE;
|
||||
|
||||
m_RecvIO.NewIOBuf(0); // 0으로 하면 기본적으로 DefaultPacketSize * 1024
|
||||
|
||||
m_hEvent = NULL; // 네트워크 이벤트 핸들러
|
||||
|
||||
ZeroMemory(m_PacketBuffer, sizeof(char)*MAX_PACKETSIZE); // Server IP저장
|
||||
|
||||
WinSockInit();
|
||||
}
|
||||
|
||||
CNetString::~CNetString(void)
|
||||
{
|
||||
OnClose();
|
||||
Stop(); // 종료 함수 호출
|
||||
|
||||
m_RecvIO.DeleteIOBuf();
|
||||
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
BOOL CNetString::WinSockInit()
|
||||
{
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
|
||||
wVersionRequested = MAKEWORD( 2, 2 );
|
||||
|
||||
err = WSAStartup( wVersionRequested, &wsaData );
|
||||
if ( err != 0 ) {
|
||||
WSACleanup();
|
||||
// Tell the user that we could not find a usable
|
||||
// WinSock DLL.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( LOBYTE( wsaData.wVersion ) != 2 ||
|
||||
HIBYTE( wsaData.wVersion ) != 2 ) {
|
||||
// Tell the user that we could not find a usable //
|
||||
// WinSock DLL. //
|
||||
WSACleanup( );
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// [1]DESCRIPTION : 클래스 초기화 //
|
||||
// [2]PARAMETER : strIPAddr - 연결IP주소, nPort - 포트번호, //
|
||||
// hWnd - 부모 윈도우 핸들 //
|
||||
// [3]RETURN : 정상 - TRUE, 실패 - FALSE //
|
||||
// [4]DATE : 2000년 9월 11일 //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
BOOL CNetString::Init( HWND hWnd, int iIndex, char* szIP, int nPort )
|
||||
{
|
||||
m_iIndex = iIndex;
|
||||
m_nPort = nPort; // 포트 번호
|
||||
unsigned long dwThreadId = 0; // 스레드 생성을 위한 변수
|
||||
|
||||
// ip 어드레스
|
||||
strcpy(m_strIPAddr,szIP);
|
||||
m_hWnd = hWnd; // 부모 핸들
|
||||
|
||||
// 연결을 시킨다. 서버로.. 만약 서버연결에 실패한다면
|
||||
// Netword Event 에서 FW_CLOSE가 발생해 소켓이 Close된다.
|
||||
if(!Connect())
|
||||
{
|
||||
// 실패했을경우 종료한다.
|
||||
Sleep(100); // Sleep...
|
||||
OnClose();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_bClose = FALSE;
|
||||
|
||||
m_hEventThread =
|
||||
(HANDLE)CreateThread(NULL, // Security
|
||||
0, // Stack size - use default
|
||||
EventThreadProc, // Thread fn entry point
|
||||
(void*) this,
|
||||
0, // Init flag
|
||||
&dwThreadId); // Thread address
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// [1]DESCRIPTION : Main Thread, 네트워크 이벤트 처리 //
|
||||
// [2]PARAMETER : void //
|
||||
// [3]RETURN : void //
|
||||
// [4]DATE : 2000년 9월 10일 //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
DWORD WINAPI CNetString::EventThreadProc(LPVOID lParam)
|
||||
{
|
||||
// 클래스를 변수로 받음
|
||||
CNetString* pThis = reinterpret_cast<CNetString*>(lParam);
|
||||
|
||||
WSANETWORKEVENTS events; // 네트워크 이벤트 변수
|
||||
BOOL bThreadRun = TRUE; // 무한 루프 변수
|
||||
|
||||
// 스레드 무한 루프
|
||||
while(bThreadRun)
|
||||
{
|
||||
if(pThis->m_bClose)
|
||||
{
|
||||
bThreadRun = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
DWORD dwRet;
|
||||
dwRet = WSAWaitForMultipleEvents(1,
|
||||
&pThis->m_hEvent,
|
||||
FALSE,
|
||||
INFINITE,
|
||||
FALSE);
|
||||
|
||||
if(!pThis->m_hSocket)
|
||||
{
|
||||
// 종료
|
||||
bThreadRun = FALSE;
|
||||
break;
|
||||
}
|
||||
// Figure out what happened
|
||||
int nRet = WSAEnumNetworkEvents(pThis->m_hSocket,
|
||||
pThis->m_hEvent,
|
||||
&events);
|
||||
|
||||
// 소켓 에러라면,
|
||||
if (nRet == SOCKET_ERROR)
|
||||
{
|
||||
bThreadRun = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
///////////////////
|
||||
// Handle events //
|
||||
bThreadRun = pThis->NetworkEventHanlder(events.lNetworkEvents);
|
||||
}
|
||||
// 이리로 스레드가 종료 되면 Server에 의한 클라이언트 종료!!! <비정상 종료>
|
||||
// 스레드 초기화는 위에서 해주기 때문에 여기서 하지는 않는다.
|
||||
// pThis->CloseAll();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CNetString::Disconnect()
|
||||
{
|
||||
// 이건 무조건 Close해줘야하기 때문에 CloseAll() 호출하지 않고 직접 끈다.
|
||||
OnClose();
|
||||
Stop(); // 종료 함수 호출
|
||||
}
|
||||
|
||||
void CNetString::Stop()
|
||||
{
|
||||
if (m_hSocket)
|
||||
{
|
||||
struct linger li = {0, 0}; // Default: SO_DONTLINGER
|
||||
|
||||
li.l_onoff = 1; // SO_LINGER, timeout = 0
|
||||
shutdown(m_hSocket, SD_BOTH ); // 오잉? 이게 뭐지? ^^;; 담에 찾아보자
|
||||
// 2001년 9월 6일
|
||||
|
||||
// 클로즈 소켓 전에 큐된 데이타를 보낼지 말지 결정하는 옵션
|
||||
setsockopt(m_hSocket, SOL_SOCKET, SO_LINGER, (CHAR *)&li, sizeof(li));
|
||||
closesocket(m_hSocket); // 소켓 닫기
|
||||
m_hSocket = NULL;
|
||||
}
|
||||
|
||||
if(m_hEvent) WSACloseEvent(m_hEvent);
|
||||
m_hEvent = NULL;
|
||||
}
|
||||
|
||||
void CNetString::CloseAll()
|
||||
{
|
||||
if(m_bConnect)
|
||||
{
|
||||
OnClose();
|
||||
Stop(); // 종료 함수 호출
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CNetString::OnClose()
|
||||
{
|
||||
m_bClose = TRUE;
|
||||
m_bConnect = FALSE; // Connect 변수 변경
|
||||
|
||||
OnSocketEvent(WM_SOCK_CLOSE, 0);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// [1]DESCRIPTION : 서버 연결을 위한 함수 //
|
||||
// [2]PARAMETER : void //
|
||||
// [3]RETURN : 정상 - TRUE, 실패 - FALSE //
|
||||
// [4]DATE : 2000년 9월 11일 //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
BOOL CNetString::Connect()
|
||||
{
|
||||
// 연결중이라면
|
||||
if(m_bConnect) return TRUE;
|
||||
|
||||
// 소켓이 남아 있다면
|
||||
Stop();
|
||||
|
||||
m_RecvIO.InitIOBuf();
|
||||
|
||||
// 소켓 생성
|
||||
m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
// 소켓 생성 검사
|
||||
if (m_hSocket == INVALID_SOCKET)
|
||||
{
|
||||
OnSocketEvent(WM_CONNECT, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// 네트워크 이벤트 핸들 생성
|
||||
m_hEvent = WSACreateEvent();
|
||||
if (m_hEvent == WSA_INVALID_EVENT)
|
||||
{
|
||||
Stop();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Request async notification
|
||||
int nRet = WSAEventSelect(m_hSocket,
|
||||
m_hEvent,
|
||||
FD_CLOSE | FD_CONNECT); // 신호를 선별하여 받게 한다
|
||||
|
||||
// 에러라면
|
||||
if (nRet == SOCKET_ERROR)
|
||||
{
|
||||
Stop();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// 비동기 방식
|
||||
unsigned long ul = 1;
|
||||
nRet = ioctlsocket(m_hSocket, FIONBIO, (unsigned long*)&ul);
|
||||
// 소켓 생성 검사
|
||||
if (m_hSocket == SOCKET_ERROR)
|
||||
{
|
||||
OnSocketEvent(WM_CONNECT, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// 소켓의 성능 최적화를 위한 세팅
|
||||
int zero = 0;
|
||||
int err = 0;
|
||||
|
||||
// Send Buffer에 대한 세팅
|
||||
if( (err = setsockopt( m_hSocket, SOL_SOCKET, SO_SNDBUF, (const char*)&zero, sizeof(zero))) == SOCKET_ERROR)
|
||||
{
|
||||
closesocket(m_hSocket);
|
||||
m_hSocket = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Receive Buffer에 대한 세팅
|
||||
if((err = setsockopt( m_hSocket, SOL_SOCKET, SO_RCVBUF, (const char*)&zero, sizeof(zero) )) == SOCKET_ERROR)
|
||||
{
|
||||
closesocket(m_hSocket);
|
||||
m_hSocket = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SOCKADDR_IN saServer;
|
||||
|
||||
memset(&saServer,0,sizeof(saServer));
|
||||
|
||||
saServer.sin_family = AF_INET;
|
||||
saServer.sin_addr.s_addr = inet_addr(m_strIPAddr);
|
||||
saServer.sin_port = htons(m_nPort);
|
||||
|
||||
// 서버와 Connect
|
||||
nRet = connect(m_hSocket,(sockaddr*)&saServer, sizeof(saServer));
|
||||
// 소켓 에러이거나 블럭킹이 되었다면
|
||||
if (nRet == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
Stop();
|
||||
return FALSE;
|
||||
}
|
||||
/*
|
||||
이렇게 Connect를 하면 서버는 AccetpEx가 성공하여 ClientSceesion은
|
||||
Recv대기상태로 들어간다.
|
||||
소켓 이벤트는 Connect가 성공하면 FD_CONNECT를 발생시킨다.
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// [1]DESCRIPTION : 네트워크 메세지를 핸들링 하여 분기 //
|
||||
// [2]PARAMETER : lEvent - 이벤트 //
|
||||
// [3]RETURN : void //
|
||||
// [4]DATE : 2000년 9월 14일 //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
BOOL CNetString::NetworkEventHanlder(LONG lEvent)
|
||||
{
|
||||
BOOL bFlag = TRUE;
|
||||
|
||||
if(lEvent & FD_CLOSE)
|
||||
{
|
||||
bFlag = FALSE;
|
||||
}
|
||||
if(lEvent & FD_CONNECT)
|
||||
{
|
||||
bFlag = OnConnect();
|
||||
}
|
||||
|
||||
return bFlag;
|
||||
}
|
||||
|
||||
void CNetString::Update()
|
||||
{
|
||||
if(!IsConnect())
|
||||
return;
|
||||
|
||||
OnSendPacketData();
|
||||
OnReadPacketData();
|
||||
|
||||
while(GetQueCnt() != 0)
|
||||
{
|
||||
int iCnt = GetPacket(m_PacketBuffer);
|
||||
|
||||
ProcessPacket(m_PacketBuffer, iCnt);
|
||||
|
||||
// printf(m_PacketBuffer);
|
||||
|
||||
PopPacket();
|
||||
}
|
||||
}
|
||||
|
||||
void CNetString::ProcessPacket(char* Packet, int PacketLen)
|
||||
{
|
||||
if(m_event)
|
||||
m_event->EventPacket(m_iIndex, Packet);
|
||||
}
|
||||
|
||||
void CNetString::SendPost(char* Packet)
|
||||
{
|
||||
// 서버로 Send 하기..
|
||||
m_SendQue.push_back(Packet);
|
||||
}
|
||||
|
||||
void CNetString::OnSendPacketData()
|
||||
{
|
||||
if(m_SendQue.empty())
|
||||
return;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Send
|
||||
int rc = 0;
|
||||
int idx = 0,size = 0;
|
||||
char send_buf[MAX_PACKETSIZE];
|
||||
|
||||
strcpy(send_buf, m_SendQue.begin()->c_str());
|
||||
size = (int)strlen(send_buf);
|
||||
|
||||
while(size > 0)
|
||||
{
|
||||
// 10004 : WSACancelBlockingCall를 호출하여 차단 작업이 중단되었습니다.
|
||||
// 10058 : 해당 소켓이 종료되었으므로 데이터 보내거나 받을 수 없습니다.
|
||||
// 10038 : 연결이 끊어진 소켓을 사용할려고 할때 난다.
|
||||
if((rc = send(m_hSocket, &send_buf[idx], size, 0)) == SOCKET_ERROR)
|
||||
{
|
||||
// 블럭킹 에러라면
|
||||
if (GetLastError() != WSAEWOULDBLOCK) // 블럭킹 에러가 아니라면
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 에러가 없다면
|
||||
size -= rc;
|
||||
idx += rc;
|
||||
}
|
||||
|
||||
m_SendQue.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void CNetString::OnReadPacketData()
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Recv
|
||||
int Ret = recv(m_hSocket, m_PacketBuffer, MAX_PACKETSIZE, 0); // 데이타 Receive
|
||||
if(Ret == 0) // Graceful close
|
||||
{
|
||||
CloseAll();
|
||||
return;
|
||||
}
|
||||
else if (Ret == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK ) // 블럭킹 에러가 아니라면
|
||||
{
|
||||
m_bConnect = FALSE;
|
||||
Stop(); // 프로그램 종료
|
||||
return;
|
||||
}
|
||||
|
||||
if(Ret > 0)
|
||||
{
|
||||
if(m_RecvIO.Append(m_PacketBuffer, Ret) == -1)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
// 받은 패킷은 IOBuffer에 넣어 처리한다.
|
||||
int iLen = m_RecvIO.GetPacket(m_PacketBuffer);
|
||||
if(iLen > 0)
|
||||
{
|
||||
// 여기서 한패킷 처리 루틴 호출
|
||||
m_RecvQue.push_back(m_PacketBuffer);
|
||||
|
||||
// Message Type 일때 이걸로 보낸다.
|
||||
// 만약 Update 이벤트 호출이면 이 루틴을 주석처리 해준다.
|
||||
OnSocketEvent(WM_RECV_MSG, iLen);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// [1]DESCRIPTION : 이벤트 처리 (On Connect) //
|
||||
// [2]PARAMETER : void //
|
||||
// [3]RETURN : false 반환 //
|
||||
// [4]DATE : 2000년 9월 11일 //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
BOOL CNetString::OnConnect()
|
||||
{
|
||||
m_bConnect = TRUE; // 연결 변수 설정 ON
|
||||
OnSocketEvent(WM_CONNECT, m_bConnect);
|
||||
|
||||
return m_bConnect;
|
||||
}
|
||||
|
||||
void CNetString::SetParent(HWND hWnd)
|
||||
{
|
||||
m_hWnd = hWnd;
|
||||
}
|
||||
|
||||
void CNetString::GetLocalIP(char* LocalIP)
|
||||
{
|
||||
char name[256];
|
||||
char* TempIp;
|
||||
PHOSTENT hostinfo;
|
||||
|
||||
WinSockInit();
|
||||
|
||||
if( gethostname ( name, sizeof(name)) == 0)
|
||||
{
|
||||
if((hostinfo = gethostbyname(name)) != NULL)
|
||||
{
|
||||
TempIp = inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list);
|
||||
strcpy(LocalIP, TempIp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
114
Server/GashServer/NetString.h
Normal file
114
Server/GashServer/NetString.h
Normal file
@@ -0,0 +1,114 @@
|
||||
#pragma once
|
||||
|
||||
#include "IOBuffer.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
// sock
|
||||
#include<winsock2.h> // win32 socket
|
||||
#pragma comment(lib,"ws2_32.lib")
|
||||
|
||||
#include<Mswsock.h> // extension socket library
|
||||
#pragma comment(lib,"mswsock.lib")
|
||||
|
||||
|
||||
#define WM_CONNECT WM_APP + 0x1001
|
||||
#define WM_RECV_MSG WM_APP + 0x1002
|
||||
#define WM_SOCK_CLOSE WM_APP + 0x1003
|
||||
|
||||
class CNetString
|
||||
{
|
||||
public:
|
||||
class IEventListener
|
||||
{
|
||||
public:
|
||||
virtual ~IEventListener() {}
|
||||
virtual void EventPacket(int iIndex, char* pPacket)=0;
|
||||
};
|
||||
|
||||
void SetEventListener(IEventListener* event)
|
||||
{
|
||||
m_event = event;
|
||||
}
|
||||
|
||||
IEventListener* m_event;
|
||||
|
||||
HWND m_hWnd; // 부모 윈도우 핸들
|
||||
int m_iIndex;
|
||||
|
||||
SOCKET m_hSocket; // 클라이언트 소켓
|
||||
UINT m_nPort; // 포트
|
||||
CHAR m_strIPAddr[20]; // Server IP저장
|
||||
|
||||
BOOL m_bConnect; // 접속 상태 플래그
|
||||
BOOL m_bClose;
|
||||
|
||||
CPacketIOBuffer m_RecvIO;
|
||||
char m_PacketBuffer[MAX_PACKETSIZE];
|
||||
|
||||
WSAEVENT m_hEvent; // 네트워크 이벤트 핸들러
|
||||
|
||||
HANDLE m_hEventThread; // Recv 스레드 핸들
|
||||
|
||||
std::list<std::string> m_SendQue;
|
||||
std::list<std::string> m_RecvQue;
|
||||
|
||||
private:
|
||||
static DWORD WINAPI EventThreadProc(LPVOID lParam); // Main Thread
|
||||
|
||||
void OnSendPacketData();
|
||||
void OnReadPacketData();
|
||||
|
||||
//////////////////
|
||||
// MessageHandling
|
||||
BOOL OnConnect(); // On Connect 신호시
|
||||
BOOL OnClose(); // On Close 신호시
|
||||
|
||||
/////////////////
|
||||
// 내부 처리 함수
|
||||
BOOL Connect(); // C-S 연결
|
||||
BOOL WinSockInit();
|
||||
|
||||
protected:
|
||||
virtual void OnSocketEvent(DWORD dID, DWORD dEvent) {};
|
||||
|
||||
BOOL NetworkEventHanlder(LONG lEvent); // 메세지 분기 함수
|
||||
void ProcessPacket(char* Packet, int PacketLen);
|
||||
|
||||
int GetQueCnt()
|
||||
{
|
||||
return (int)m_RecvQue.size();
|
||||
}
|
||||
|
||||
int GetPacket(char* pPacket)
|
||||
{
|
||||
strcpy(pPacket, m_RecvQue.begin()->c_str());
|
||||
return (int)strlen(pPacket);
|
||||
}
|
||||
|
||||
void PopPacket()
|
||||
{
|
||||
m_RecvQue.pop_front();
|
||||
}
|
||||
|
||||
public:
|
||||
void GetLocalIP(char* LocalIP);
|
||||
|
||||
BOOL IsConnect() { return m_bConnect; }
|
||||
|
||||
virtual void SendPost(char* Packet);
|
||||
|
||||
// 시작 종료함수.
|
||||
BOOL Init(HWND hWnd, int iIndex, char* szIP, int nPort); // 초기화
|
||||
virtual void Disconnect();
|
||||
|
||||
virtual void Update();
|
||||
|
||||
void Stop(); // 클라이언트 정지
|
||||
void CloseAll();
|
||||
void SetParent(HWND hWnd);
|
||||
|
||||
public:
|
||||
CNetString(void);
|
||||
~CNetString(void);
|
||||
};
|
||||
32
Server/GashServer/ReadMe.txt
Normal file
32
Server/GashServer/ReadMe.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
========================================================================
|
||||
콘솔 응용 프로그램 : GashServer 프로젝트 개요
|
||||
========================================================================
|
||||
|
||||
응용 프로그램 마법사에서 이 GashServer 응용 프로그램을 만들었습니다.
|
||||
|
||||
이 파일에는 GashServer 응용 프로그램을 구성하는 각 파일에 대한
|
||||
요약 설명이 포함되어 있습니다.
|
||||
|
||||
|
||||
GashServer.vcproj
|
||||
응용 프로그램 마법사를 사용하여 생성한 VC++ 프로젝트의 기본 프로젝트 파일입니다.
|
||||
파일을 생성한 Visual C++ 버전에 대한 정보와 응용 프로그램 마법사를 사용하여 선택한
|
||||
플랫폼, 구성 및 프로젝트 기능에 대한 정보가 포함되어 있습니다.
|
||||
|
||||
GashServer.cpp
|
||||
기본 응용 프로그램 소스 파일입니다.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
기타 표준 파일:
|
||||
|
||||
StdAfx.h, StdAfx.cpp
|
||||
이 파일은 미리 컴파일된 헤더(PCH) 파일인 GashServer.pch와
|
||||
미리 컴파일된 형식(PCT) 파일인 StdAfx.obj를 빌드하는 데 사용됩니다.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
기타 참고:
|
||||
|
||||
응용 프로그램 마법사에서 사용하는 "TODO:" 주석은 사용자가 추가하거나 사용자 지정해야 하는
|
||||
소스 코드 부분을 나타냅니다.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
88
Server/GashServer/Sync.h
Normal file
88
Server/GashServer/Sync.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // 거의 사용되지 않는 내용은 Windows 헤더에서 제외합니다.
|
||||
|
||||
namespace Nave { namespace Sync {
|
||||
/*
|
||||
class CTest : public CMTSync<CTest>
|
||||
{
|
||||
public:
|
||||
void Test()
|
||||
{
|
||||
CTSync Sync;
|
||||
}
|
||||
};
|
||||
*/
|
||||
class CSync
|
||||
{
|
||||
public:
|
||||
CSync(VOID)
|
||||
{
|
||||
InitializeCriticalSection(&mSync);
|
||||
}
|
||||
|
||||
~CSync(VOID)
|
||||
{
|
||||
DeleteCriticalSection(&mSync);
|
||||
}
|
||||
|
||||
inline VOID Enter(VOID)
|
||||
{
|
||||
EnterCriticalSection(&mSync);
|
||||
}
|
||||
|
||||
inline VOID Leave(VOID)
|
||||
{
|
||||
LeaveCriticalSection(&mSync);
|
||||
}
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION mSync;
|
||||
};
|
||||
|
||||
class CSSync
|
||||
{
|
||||
public:
|
||||
CSSync(LPVOID lpVoid)
|
||||
{
|
||||
m_pThis = (CSync*)lpVoid;
|
||||
m_pThis->Enter();
|
||||
}
|
||||
|
||||
~CSSync(VOID)
|
||||
{
|
||||
if(m_pThis)
|
||||
m_pThis->Leave();
|
||||
}
|
||||
|
||||
protected:
|
||||
CSync *m_pThis;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class CMTSync
|
||||
{
|
||||
friend class CTSync;
|
||||
public:
|
||||
class CTSync
|
||||
{
|
||||
public:
|
||||
CTSync(VOID)
|
||||
{
|
||||
T::mSync.Enter();
|
||||
}
|
||||
|
||||
~CTSync(VOID)
|
||||
{
|
||||
T::mSync.Leave();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
static CSync mSync;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
CSync CMTSync<T>::mSync;
|
||||
|
||||
}}
|
||||
8
Server/GashServer/stdafx.cpp
Normal file
8
Server/GashServer/stdafx.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : 표준 포함 파일만 들어 있는 소스 파일입니다.
|
||||
// GashServer.pch는 미리 컴파일된 헤더가 됩니다.
|
||||
// stdafx.obj에는 미리 컴파일된 형식 정보가 포함됩니다.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: 필요한 추가 헤더는
|
||||
// 이 파일이 아닌 STDAFX.H에서 참조합니다.
|
||||
17
Server/GashServer/stdafx.h
Normal file
17
Server/GashServer/stdafx.h
Normal file
@@ -0,0 +1,17 @@
|
||||
// stdafx.h : 자주 사용하지만 자주 변경되지는 않는
|
||||
// 표준 시스템 포함 파일 및 프로젝트 관련 포함 파일이
|
||||
// 들어 있는 포함 파일입니다.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _WIN32_WINNT // Windows XP 이상에서만 기능을 사용할 수 있습니다.
|
||||
#define _WIN32_WINNT 0x0501 // 다른 버전의 Windows에 맞도록 적합한 값으로 변경해 주십시오.
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
|
||||
|
||||
|
||||
// TODO: 프로그램에 필요한 추가 헤더는 여기에서 참조합니다.
|
||||
Reference in New Issue
Block a user