[codechaser님의 nateon protocol 문서중에서...]
'프로그래밍/네트워크'에 해당되는 글 10건
- 2010/01/05 Payload?
- 2010/01/04 프로토콜
- 2009/12/28 IOCP 관련 팁
- 2008/11/19 [온라인 게임 서버]2장 온라인 게임 서버(기초편)
- 2008/11/18 [온라인 게임 서버]1장 온라인 게임 서버(시작편)
- 2008/11/18 [온라인 게임 서버]목차
- 2008/01/29 ACE 구조
- 2007/08/22 소켓의 초기화
- 2007/08/06 소켓2의 사용
- 2007/03/21 Beginning Winsock Programming - Simple TCP server(코드프로젝트)
[codechaser님의 nateon protocol 문서중에서...]
msn 프로토콜 : http://www.hypothetic.org/docs/msn/
nateon 프로토콜 : http://blog.naver.com/PostView.nhn?blogId=codechaser&logNo=80042584567&categoryNo=3&parentCategoryNo=0&viewDate=¤tPage=1&postListTopCurrentPage=1&isAfterWrite=true
이런거 이렇게 정리 잘 해 놓는 분들 대단하십니다...
댓글을 달아 주세요
팁1.
IOCP는 작업의 완료 시에 읽기 작업을 끝냈는지 쓰기 작업을 끝냈는지 가르쳐 주지 않는다는 것이다.
따라서, OVERLAPPED구조체를 상속하여 읽기 작업을 하는 건지 쓰기 작업을 하는 건지에 대한 흔적을 남겨야 한다.
팁2.
프로그래머는 항상 패킷퍼버에 있는 내용을 원하는 크기만큼 읽고 쓸수 있다고 생각하면 안된다.
이는 네트워크 상의 여러가지 문제 따라서 얼마나 읽고 쓸 수 있는 변한다. 그러므로 원하는 만큼의 데이터인지 확인 해야 한다.
이러한 이유로 패킷에 길이에 대한 정보가 추가 되어야 한다.
팁3.
팁4.
비동기 입출력에 관한 정리
Asynchronous I/O and The Asynchronous Disk I/O Explorer : http://www.flounder.com/asynchexplorer.htm
'프로그래밍 > 네트워크' 카테고리의 다른 글
| 프로토콜 (0) | 2010/01/04 |
|---|---|
| IOCP 관련 팁 (0) | 2009/12/28 |
| [온라인 게임 서버]2장 온라인 게임 서버(기초편) (0) | 2008/11/19 |
| [온라인 게임 서버]1장 온라인 게임 서버(시작편) (0) | 2008/11/18 |
댓글을 달아 주세요
온라인 게임 서버(기초편)
2.1 소켓
2.1.1 소켓이란
- 1982년 BSD 유닉스에 소개
2.1.2 소켓의 유형(스트림 소켓과 데이터 그램 소켓
- TCP/IP : 스트림 방식, 양방향 연결
- UDP/IP : 데이터 그램 방식
2.1.3 소켓의 동작 모드(blocking, non-blocking)
- 블러킹 : 기본 모드, 작업 완료 해야 반환
- 넌 블러킹 : ioctlsocket()로 바꿔준다
2.2 윈속(Winsock)
- winsock 2.2
2.2.1 연결지향형 통신
클라이언트 : socket() -> connect() -> recv(), send(), closesocket()
|
+-------------+
|
서버 : socket() -> bind() -> listen() -> accept() -> recv(), send() -> closesocket()
2.2.1.1 소켓 생성 함수
- SOCKET socket(int af, int type, int protocol)
- 소켓을 생성하여 반환
SOCKET sockNew = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(INVALID_SOCKET == sockNew)
{
//에러처리}
2.2.1.2 클라이언트 측 함수
2.2.1.3 서버측 함수
2.2.1.4 데이터 전송 함수
2.2.1.5 연결 종료 함수
2.2.2 비연결지향형 통신
2.2.3 그 외 함수들
2.3 쓰레드(Thread)
2.3.1 C런타임 라이브러리
2.3.2 Win32 라이브러리
2.3.3 쓰레드 종료
2.4 동기화(Syncronization)
2.4.1 커널 객체(Kernel Object)
2.4.2 커널모드와 유저모드(Kernel Mode and User Mode)
2.4.3 유저 모드에서의 동기화
2.4.4 커널 모드에서의 동기화
2.4.4.1 이벤트(Event)
2.4.4.2 뮤텍스(Mutex)
2.4.4.3 세마포어(Semaphore)
2.5 Windows I/O 모델
- select, WSAAsyncSelect, WSAEventSelect, Overlapped I/O(Event), Overlapped I/O(Callback), Completion Port I/O(Non-Albetrable), Completion Port I/O(Albetrable)
2.5.1 select 모델
2.5.2 WSAAsynSelect 모델
- int WSAAsyncSelect(SOCKET s,
HWND hWnd,
unsigned int wMsg,
long lEvent);
- 소켓 입출력을 윈도우 메세지로 통보(윈도우가 반드시 있어야 함)
- lEvent : FD_READ, FD_WRITE, FD_OOB, FD_ACCEPT, FD_CONNECT, FD_CLOSE
2.5.3 WSAEventSelect 모델
- 윈도우 없이 사용 가능
- int WSAEventSelect( SOCKET s,
WSAEVENT hEventObject,
long lNetworkEvents );
2.5.4 Overlapped I/O 모델
- 중첩 입출력
2.5.4.1 Overlapped I/O 모델 특징
- 비동기 데이터 송수신(동시에 여러개의 데이터를 송수신 요청 가능)
- 소켓 내부 버퍼를 사용하지 않고 TCP전송 버퍼에서 데이터 송수신(소켓 옵션 함수에서 내부 버퍼를 0으로 만들어 줌)
- 주의 : 데이터를 보낼 때는 작업이 완료되기 전에 버퍼를 삭제하면 안된다.
- SOCKET WSASocket(
int af,
int type,
int protocol,
LPWSAPROTOCOL_INFO lpProtocolInfo, //NULL(소켓생성프로바이더)
GROUP g, // 0 (소켓 그룹)
DWORD dwFlags ); //WSA_FLAG_OVERLAPPED(OverlappedI/O)
- int WSASend(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount, //WSABUF 개수
LPWORD lpNumberOfBytesSent,
DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE );
- int WSARecv(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPWORD lpNumberOfBytesSent,
LPDWORD lpFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTIN lpCompletionROUTINE);
- WSAOVERLAPPED 는 내부적으로 사용되어지는 변수로 첫번째부터 네번째변수는 0으로 초기화 해야함(이상동작), hEvent는 완료를 알려주는 역할
- 반환값이 0이 아닐때 WSA_IO_PENDING은 즉시처리되지 않고 나중에 처리될 예정 그 외는 에러
2.5.4.2 Overlapped I/O - Event 모델
- WSAWaitForMultipleEvents() : 이벤트 발생 감지
- BOOL WSAGetOverlappedResult(
SOCKET s,
LPWSAOVERLAPPED lpOverlapped,
LPDWORD lpcbTransfer,
BOOL fWait, //Overlapped I/O 작업이 완료할때까지 대기 여부(FALSE)
LPDWORD lpdwFlags );
: 작업 완료 이벤트 발생 소켓에서 작업 결과를 갖고온다.
2.5.4.3 Overlapped I/O - Callback 모델
- 작업완료 통보를 콜백함수 호출
- void CALLBACK CompletionROUTINE(
DWORD dwError,
DWORD cbTransferred, //처리바이트수(실패:0)
LPWSAOVERLAPPED lpOverlapped,
DWORD dwFlags );
2.5.4.4 I/O Completion Port 모델
- 윈도우 모델에서 최고성능
- Windows NT 4.0 이상
- Overlapped I/O + Thread Pooling
- 쓰레드 풀 : 여러 쓰레드를 미리 대기상태로 생성 해 놓음
- 쓰레드 생성/소멸 에 따른 cpu 소모 줄임
- Context Switching 을 줄임
- CreateIoCompletionPort()
- IOCP Queue
- WaitngThread Queue : LIFO (Context Switching을 줄이기 위함)
- HANDLE CreateIoCompletionPort(
HANDLE FileHandle,
HANDLE ExistingCompletionPort,
ULONG_PTR CompletionKey,
DWORD NumberOfConcurrentThreads );
: CompletionPort 커널 객체 생성, CompletionPort 커널 객체와 소켓을 연결
: 생성시에는 마지막 인자만 사용 (0 : cpu개수와 동일하게 설정)
CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, NULL, 2);
: 연결시에는 첫번째(CompletionPort와 연결될 소켓핸들), 두번째(생성된 CompletionPort 객체), 세번째(어떤 소켓인지 구분하기 위한 고유값), 네번째(0:무시)
- BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort,
LPDWORD lpNumberOfBytes,
PULONG_PTR lpCompletionKey,
LPOVERLAPPED* lpOverlapped,
DWORD dwMilliseconds );
: 실패시 FALSE 반환 : lpNumberOfBytes가 0이면 소켓이 닫힘
: 세번째 인자는 CreateIoCompletionPort에서 넣어 주었던 값
- BOOL PostQueuedCompletionStatus(
HANDLE CompletionPort,
DWORD dwNumberOfBytesTransferred,
ULONG_PTR dwCompletionKey,
LPOVERLAPEED lpOverlapped );
: 사용자가 인자로 넣어준 정보를 IOCP Queue에 추가
'프로그래밍 > 네트워크' 카테고리의 다른 글
| IOCP 관련 팁 (0) | 2009/12/28 |
|---|---|
| [온라인 게임 서버]2장 온라인 게임 서버(기초편) (0) | 2008/11/19 |
| [온라인 게임 서버]1장 온라인 게임 서버(시작편) (0) | 2008/11/18 |
| [온라인 게임 서버]목차 (0) | 2008/11/18 |
댓글을 달아 주세요
1.1 시작하기 전에
- 기초지식, 서론
1.2 온라인 게임 서버 개요
1.2.1 어떤 온라인 게임 서버를 만들 것인가?
- 서버의 구조
1.2.2 채널 형 게임 서버 구조
- 채널형 게임서버 : 고스톱, 테트리스, 포트리스, 크레이지 아케이드
- 채널별 (100~500명 제한) -> 방(2~8명이 게임)
1.2.3 MMO형 게임 서버 구조
- MMO : Massively Multi-players Online)
- 리니지, 뮤 온라인 라그나로크
- 존(Zone) 영역
'프로그래밍 > 네트워크' 카테고리의 다른 글
| [온라인 게임 서버]2장 온라인 게임 서버(기초편) (0) | 2008/11/19 |
|---|---|
| [온라인 게임 서버]1장 온라인 게임 서버(시작편) (0) | 2008/11/18 |
| [온라인 게임 서버]목차 (0) | 2008/11/18 |
| ACE 구조 (0) | 2008/01/29 |
댓글을 달아 주세요
전체 목차
'프로그래밍 > 네트워크' 카테고리의 다른 글
| [온라인 게임 서버]1장 온라인 게임 서버(시작편) (0) | 2008/11/18 |
|---|---|
| [온라인 게임 서버]목차 (0) | 2008/11/18 |
| ACE 구조 (0) | 2008/01/29 |
| 소켓의 초기화 (0) | 2007/08/22 |
댓글을 달아 주세요
WS2_32.dll을 사용할 수 있도록 해주는 함수입니다.
int WSAStartup(
[in]WORD wVersionRequested, //소켓의 버전정보
[out]LPWSADATA lpWSAData //윈속에 대한 정보 구조체 포인터
);
- 성공을 하면 0값을 리턴
- 사용이 끝나고 나면 WSACleanup() 호출
예제코드
WORD wVersionRequested;
WSADATA wsaData;
int err;//버전 2.2
wVersionRequested = MAKEWORD(2, 2);err = WSAStartup(wVersionRequested, &wsaData);
if( err != 0 )
{
//초기화실패
WSACleanup();
return;
}
if( LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2 )
{
//2.2버전 dll이 없으므로
WSACleanup();
return;
}
댓글을 달아 주세요
소켓2를 사용하고자 할때는
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
를 추가해서 사용합니다.
MFC의 소켓 클래스를 사용할 afxsock.h에서도 소켓2를 사용하기 위해서는
#pragma comment(lib, "ws2_32.lib")
명시해 주면 됩니다.
댓글을 달아 주세요
윈속api는 마이크로소프트 윈도우 운영체제를 위한 소켓 프로그래밍 라이브러리이다.
윈속은 버클리소켓을 기반으로 만들어졌다.
그렇지만 대부분 마이크로소프트는 채용하면서 형태를 바꾼다.
이 기사에서 나는 소개하기위해 시도할 것이다. 당신이 어떤한 운영체제에서도 네트워크 프로그래밍 같은 것을 해본적이 없다는 가정하에 WinSock을 이용하여 소켓프로그래밍을 할 수 있게 할 것이다.
컴퓨터가 한대밖에 없다고 해서 걱정할 일도 없다. WinSock 프로그램은 로컬 루프 백 주소인 127.0.0.1을 호출하여 할 수 있다.
그러므로 만약 당신이 TCP 서버를 돌리는 당신의 컴퓨터에서 돌린다 해도, 클라이언트 프로그램은 동일한 컴퓨터에서 서버에 연결할수 있다.
Simple TCP Server
이 기사에서 WinSock을 이용한 차례차례 만들어갈수 있는 간단한 TCP 서버를 소개할 것이다.
시작하기전에 몇가지 해야할 것이 있다. WinSock 프로그램을 시작하기전에 해야할 것들이다.
Win32 콘솔 어플리케이션을 VC++6.0 어플리케이션 위저드를 이용하여 만든다.
MFC를 지원하는 옵션을 선택하는것을 기억해야 한다.
#include 를 stdafx.h에 추가해야 한다.
winsock2.h 다음에는 #include conio.h와 iostream.h도 해주어야 한다.
Project-Settings-Link에서 ws2_32.lib 를 library modules 리스트에 적어준다.
The main function
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
cout < < "Press ESCAPE to terminate program\r\n";
AfxBeginThread(ServerThread,0);
while(_getch()!=27);
return nRetCode;
}
main() 에서 하는 것은 Thread를 시작하고, 루프를 돌며 _getch() 함수를 호출한다.
_getch()는 단순히 키가 눌리기 전이나, 반환한 아스키 값을 받을때 까지 기다린다.
ESCAPE 키의 아스키 코드 값인 27의 값이 리턴되기 전까지 루프를 돈다.
ESCAPE을 누르는 것을 쓰레드가 시작되어서 아직 활성화 되어있기 때문에 항상 고려해야 한다.
그런 모든것들에 대해 걱정하지 마라.
main()이 리턴할때는 프로세스는 종료되었거나 쓰레드가 시작되었는데 주 쓰레드가 갑자기 종료되는 경우이다.
The ServerThread function
내가 지금 하려는 것은 서버 쓰레드 함수의 나열과 사용한 코드의 설명을 하기 위한 주석이다. 각 라인의 코드들에 대한 설명이다.
기본적으로 우리의 TCP 서버는 이와 같은 것을 해야 한다.
20248 포트에서 나의 코드 프로젝트 멤버쉽 아이디 입력하는 것을 listen 한다.
동시에 Talk 한다.
클라이언트가 접속했을때, 서버는 메세지를 돌려 보내고 클라이언트에게 줄 IP 주소와 연결을 닫고 연결 수락을 돌려 보낼때
20248포트로 보낼것이다.
실행하며 특정 IP주소로 부터 연결을 해서 콘솔에 한줄을 찍을 것이다.
쓸모없는 프로그램이라고 생각될 것이다.
사실 몇몇 어떤 이들은 할것이다 종종 생각을 이 필요없는 SNDREC32.EXE 윈도우에서는
터무니 없이 그들에게 말한다.
UINT ServerThread(LPVOID pParam)
{
cout << "Starting up TCP server\r\n";
//A SOCKET is simply a typedef for an unsigned int.
//In Unix, socket handles were just about same as file
//handles which were again unsigned ints.
//Since this cannot be entirely true under Windows
//a new data type called SOCKET was defined.
SOCKET server;
//WSADATA is a struct that is filled up by the call
//to WSAStartup
WSADATA wsaData;
//The sockaddr_in specifies the address of the socket
//for TCP/IP sockets. Other protocols use similar structures.
sockaddr_in local;
//WSAStartup initializes the program for calling WinSock.
//The first parameter specifies the highest version of the
//WinSock specification, the program is allowed to use.
int wsaret=WSAStartup(0x101,&wsaData);
//WSAStartup returns zero on success.
//If it fails we exit.
if(wsaret!=0){ return 0;
}
//Now we populate the sockaddr_in structure
local.sin_family=AF_INET;
//Address family
local.sin_addr.s_addr=INADDR_ANY;
//Wild card IP address
local.sin_port=htons((u_short)20248);
//port to use
//the socket function creates our
SOCKET server=socket(AF_INET,SOCK_STREAM,0);
//If the socket() function fails we exit
if(server==INVALID_SOCKET)
{
return 0;
}
//bind links the socket we just created with the sockaddr_in
//structure. Basically it connects the socket with
//the local address and a specified port.
//If it returns non-zero quit, as this indicates error
if(bind(server,(sockaddr*)&local,sizeof(local))!=0)
{
return 0;
}
//listen instructs the socket to listen for incoming
//connections from clients. The second arg is the backlog
if(listen(server,10)!=0)
{
return 0;
}
//we will need variables to hold the client socket.
//thus we declare them here.
SOCKET client;
sockaddr_in from;
int fromlen=sizeof(from);
while(true)
//we are looping endlessly
{
char temp[512];
//accept() will accept an incoming
//client connection
client=accept(server, (struct sockaddr*)&from,&fromlen);
sprintf(temp,"Your IP is %s\r\n",inet_ntoa(from.sin_addr));
//we simply send this string to the client
send(client,temp,strlen(temp),0);
cout << "Connection from " << inet_ntoa(from.sin_addr) <<"\r\n";
//close the client socket
closesocket(client);
}
//closesocket() closes the socket and releases the socket descriptor
closesocket(server);
//originally this function probably had some use
//currently this is just for backward compatibility
//but it is safer to call it as I still believe some
//implementations use this to terminate use of WS2_32.DLL
WSACleanup();
return 0;
}
Testing it out
서버가구동되고 사용자가 텔넷을 사용하여 실행중인 서버의 20248포트로 접속한다.
동일 컴퓨터에서 접속한다면 localhost로 접속한다.
Sample Output
서버에서 아래와 같은 출력화면을 볼수 있응ㄹ것이다.
E:\work\Server\Debug>server
Press ESCAPE to terminate program Starting up TCP server Connection from 203.200.100.122 Connection from 127.0.0.1
E:\work\Server\Debug>
그리고 클라이언트에서 얻은 정보이다.
nish@sumida:~$ telnet 202.89.211.88 20248 Trying 202.89.211.88… Connected to 202.89.211.88. Escape character is ‘^]’. Your IP is 203.200.100.122 Connection closed by foreign host. nish@sumida:~$
Conclusion
간단한 TCP서버를 만들어 보았다.
by Redef( http://www.redef.pe.kr )
댓글을 달아 주세요