Presentation is loading. Please wait.

Presentation is loading. Please wait.

범용 소켓 클래스 만들기.

Similar presentations


Presentation on theme: "범용 소켓 클래스 만들기."— Presentation transcript:

1 범용 소켓 클래스 만들기

2 Contents 예제 서버 클라이언트 채팅 소스 분석 및 관련 API Overview

3 Overview of MS .NET

4 MFC Library

5 Classical Win32 API Programming
Use C to access raw API functions directly No C++ class library wrappers to hide API Hard way to go, but most basic Faster executables Provides understanding of how Windows and application program interact Establishes a firm foundation for MFC programming

6 MFC Library Microsoft’s C++ Interface to Windows API
O-O Approach to Windows Programming Some 200 classes API functions encapsulated in the MFC Classes derived from MFC do grunt work Just add data/functions to customize app Provides a uniform application framework

7 The Event-Driven Paradigm

8 CASyncSocket을 상속받아 만들기
서버클래스 클라이언트클래스 CASyncSocket pSocket pSocket->Create(2000) pSocket->Listen() CAsyncSocket pSocket pSocket->Create(); pSocket->Connect(Adr,2000); pSocket pSocket->Receive(data); pSocket->Send(“나도안녕!”) CASyncSocket Sock pSocket->Accept(Sock) Sock.Send(“안녕”) Sock.Receive(data);

9 CAsyncSocket의 특정 멤버함수 OnAccept(); 클라이언트가 Connect를 실행하여 서버에 접속하고자 할 때 서버에서는 새로운 클라이언트가 들어오면 OnAccept함수가 실행된다. OnReceive(); 새로운 데이터가 들어왔을 경우에는 OnReceive라는 함수가 실행됨. 즉 새로운 클라이언트가 접속을 실행하면 메시지를 날려주는 것이 아니라 OnAccept()함수가 실행되고 또한 새로운 데이터가 들어왔을때는 OnReceive()함수가 실행됨 CMySocket::public CAsyncSocket{ public: virtual void OnAccept(int nErrorCode); virtual void OnReceive(int nErrorCode); }

10 서버클래스(CServerSock) #include "client~1.h"
#define WM_ACCEPT_SOCKET WM_USER+1 class CSeverSock : public CAsyncSocket { public: CSeverSock(); //메세지를 전달할 HWND설정 void SetWnd(HWND hwnd); //현재 클라이언트와 연결된 소켓을 받는다. CClientSock* GetAcceptSocket(); //새로운 클라이언트가 연결되었을대 virtual void OnAccept( int nErrorCode ); //새로운 클라이언트 가 연결되었을때 //Accept할 소켓 클래스 변수 CClientSock m_pChild; HWND m_pHwnd; }

11 서버클래스(CServerSock) #include "stdafx.h" #include "sversok.h" //생성자
//새로운 클라이언트가 연결되었을때 //실행되는 함수 void CSeverSock::OnAccept( int nErrorCode ) { TRACE("Errocode = %d",nErrorCode); //클라이언트 클래스인 m_pChild로 연결시켜준다. Accept(m_pChild); //새로운 클라이언트가 연결되었다는 //WM_ACCEPT_SOCKET 메세지를 전달합니다. SendMessage(m_pHwnd,WM_ACCEPT_SOCKET,0,0); } //OnAccept함수 실행후 새로운 클라이언트와 연결된 //m_pChild 소켓을 넘겨줍니다. CClientSock* CSeverSock::GetAcceptSocket() return &m_pChild; #include "stdafx.h" #include "sversok.h" //생성자 CSeverSock::CSeverSock() { CAsyncSocket::CAsyncSocket(); } //메세지를 전달할 윈도우 설정 void CSeverSock::SetWnd(HWND hwnd) m_pHwnd=hwnd;

12 클라이언트클래스(CClientSock)
//clientsok.h //클라이언트용 소켓 프로그램 헤더 #define WM_RECEIVE_DATA WM_USER+2 class CClientSock : public CAsyncSocket { public: CClientSock(); //메세지를 전달할 HWND를 설정하는 함수 void SetWnd(HWND hwnd); //새로운 데이타가 들어왔을대 실행되는 함수 virtual void OnReceive( int nErrorCode ); //메세지를 전달할 HWND HWND m_pHwnd; };

13 클라이언트클래스(CClientSock)
#include "stdafx.h" #include "Clientsok.h" //생성자는 아무일도 안하고 모든생성을 CAsyncSocket에 넘겨줍니다. CClientSock::CClientSock() { CAsyncSocket::CAsyncSocket(); } //데이타가 들어왔을때 현재 hwnd에 새로운 데이타가 들어 //왔다는 메세지를 날려주기위한 hwnd를 설정합니다. void CClientSock::SetWnd(HWND hwnd) m_pHwnd=hwnd; //새로운 데이타가 들어왔을때 현재의 hwnd에 //USER+2인 메세지 WM_RECEIVE를 보냅니다. void CClientSock::OnReceive( int nErrorCode ) TRACE("Errocode = %d",nErrorCode); SendMessage(m_pHwnd,WM_RECEIVE_DATA,0,0);

14 서버프로그램 만들기 LONG CEx3101View::OnAccept(UINT wParam,LONG lParam) {
//새로운 클라이언트와 연결할 소켓을 만들고 m_pChildSock = new CClientSock; //서버 소켓으로부터 현재 연결된 소켓을 받는다. m_pChildSock = m_pSeverSock->GetAcceptSocket(); //hwnd설정 m_pChildSock->SetWnd(this->m_hWnd); char temp[200]; //안녕하세요 라는 데이타를 보낸다. sprintf(temp,"안녕하세요?"); m_pChildSock->Send((LPSTR)temp,200); return TRUE; }

15 구현하고자 하는 기능 어떤 프로그램에서든 사용 가능한 소켓 클래스를 만든다. 서버 소켓 클래스(CServerSocket)
CSocket클래스에서 상속, 서버에서 클라이언트의 접속요청을 받아들이고 데이터 소켓을 연결. 데이터 소켓 클래스(CDataSocket) Csocket 클래스에서 상속, 실제로 데이터를 주고 받는 기능, 클라이언트 소켓으로 서버에 접속 요청. 데이터 구조 클래스(Cdata) 데이터 포맷을 같도록 해준다.

16 서버프로그램 만들기 void CEx3101View::OnInitialUpdate() {
CFormView::OnInitialUpdate(); //서버 소켓을 만든다. m_pSeverSock = new CSeverSock; //서버 소켓의 현재view의 hwnd를 설정한다. //이렇게 설정해놓아야 현 View로 메세지가 전달됨 m_pSeverSock->SetWnd(this->m_hWnd); // 2000번 포트번호로 소켓을 만든다. m_pSeverSock->Create(2000); //클라이언트가 오기를 기다린다. m_pSeverSock->Listen(); } 새로운 클라이언트가 접속했을때 CServerSock은 WM_ACCEPT_SOCKET(WM_USER+1)의 메시지를 발생키시고 이메시지가 발생될 때 실행되는 함수 OnAccept가 있다고 하면 우선 BEGIN_MESSAGE_MAP에 다음과 같이 한다. ON_MESSAGE(WM_ACCEPT_SOCKET, OnAccept) 헤더에는 다음과 같이 한다. afx_msg LONG OnAccept(UINT wParam, LONG lParam)

17 서버프로그램 만들기 //새로운 데이타가 들어왔을때
LONG CEx3101View::OnReceive(UINT wParam,LONG lParam) { char temp[200]; //소켓으로 부터 데이타를 받은다음 m_pChildSock->Receive((LPSTR)temp,200); //화면과 연결된 m_strReceive에 설정한다. m_strReceive=temp; UpdateData(FALSE); return TRUE; } //데이타 보내기 버튼을 눌렀을때 void CEx3101View::OnSend() UpdateData(TRUE); //에디터에 입력한 데이타를 받아서 lstrcpy((LPSTR)temp,(LPSTR)m_strSend.operator const char*()); //클라이언트에 보낸다. m_pChildSock->Send(temp,200);

18 클라이언트 프로그램 만들기 LONG CEx3102View::OnReceive(UINT wParam,LONG lParam) {
char temp[200]; m_pClientSock->Receive((LPSTR)temp,200); m_strReceive=temp; UpdateData(FALSE); return TRUE; } void CEx3102View::OnSend() UpdateData(TRUE); lstrcpy((LPSTR)temp,(LPSTR)m_strSend.operator const char*()); m_pClientSock->Send(temp,200);

19 클라이언트 프로그램 만들기 #include "setip.h" void CEx3102View::OnInitialUpdate()
{ CFormView::OnInitialUpdate(); m_pClientSock=new CClientSock; //IP주소를 묻는 대화상자가 실행된다. CSetIp *pDlg = new CSetIp; if(pDlg->DoModal()==IDOK) char temp[80]; lstrcpy((LPSTR)temp,(LPSTR)pDlg->m_strIp.operator const char*()); //temp 에 입력한 ip주소를 설정한다. m_pClientSock->Create(); //IP 주소와 함께 포트번호 2000을 설정하여 //클라이언트에 접속을 시도한다. m_pClientSock->Connect(temp,2000); //메세지를 받을 HWND설정 m_pClientSock->SetWnd(this->m_hWnd); }

20 서버소켓 CServerSocket 클래스 만들기
접속 요청이 들어오면 받아들이는 일은 main window에서 수행(범용성 고려) 접속요청이 들어오면 CServerSocket 의 OnAccept가 자동으로 호출 OnAccept -> UM_ACCEPT #define UM_ACCEPT(WM_USER)

21 CServerSocket #define UM_ACCEPT (WM_USER)
class CServerSocket : public CSocket { // Attributes public: // Operations CServerSocket(); virtual ~CServerSocket(); // Overrides void Init(CWnd *pWnd, int nPortNum); CWnd *m_pWnd; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CServerSocket) virtual void OnAccept(int nErrorCode); void CServerSocket::Init(CWnd *pWnd, int nPortNum) { m_pWnd = pWnd; Create(nPortNum);//소켓 생성 Listen();//접속 요청 감지 } void CServerSocket::OnAccept(int nErrorCode) m_pWnd->SendMessage(UM_ACCEPT); CSocket::OnAccept(nErrorCode);

22 데이터 소켓 CDataSocket 클래스만들기
실제로 데이터를 송수신 하는 기능 담당 범용성을 위해 새로운 데이터가 수신 되었을때 OnReceive 함수에서 UM_DATARECEIVE메세지를 메인 윈도우에 보냄. #define UM_DATARECEIVE (WM_USER+1) void CDataSocket::OnReceive(int nErrorCode) { m_pWnd->SendMessage(UM_DATARECEIVE); CSocket::OnReceive(nErrorCode); } 송신 : Send, Flush, << 수신 : Receive, >>

23 CDataSocket Header file
class CDataSocket : public CSocket { // Attributes public: CWnd *m_pWnd; CSocketFile *m_pFile; CArchive *m_pArchiveIn; CArchive *m_pArchiveOut; // Operations CDataSocket(); virtual ~CDataSocket(); // Overrides void operator << (CData &data); void operator >> (CData &data); void Flush(); void Send(CData *pData); void Receive(CData *pData); void Init(CWnd *pWnd); // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CDataSocket) public: virtual void OnReceive(int ErrorCode); virtual void OnClose(int nErrorCode); //}}AFX_VIRTUAL // Generated message map functions //{{AFX_MSG(CDataSocket) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG // Implementation protected: };

24 CDataSocket Souce File
데이터소켓 초기화 pWnd : 메시지를 받을 윈도우 데이터 수신용, 송신용 Carchieve void CDataSocket::Init(CWnd *pWnd) { m_pWnd = pWnd; m_pFile = new CSocketFile(this); m_pArchiveIn = new CArchive(m_pFile, CArchive::load); m_pArchiveOut = new CArchive(m_pFile, CArchive::store); } 데이터수신 Carchieve 클래스를 이용하여 Serialize함수를 호출 void CDataSocket::Receive(CData * pData) { if(m_pArchiveIn != NULL) pData->Serialize(*m_pArchiveIn); } void CDataSocket::operator >>(CData & data) Receive (&data);

25 CDataSocket Souce File
데이터 송신 Serialize 함수를 이용 소켓이 관리하는 송신용 버퍼에 저장만 된다. Flush()사용 void CDataSocket::Send(CData * pData) { if(m_pArchiveOut != NULL) pData->Serialize(*m_pArchiveOut); } void CDataSocket::Flush() m_pArchiveOut->Flush(); void CDataSocket::operator <<(CData & data) Send (&data); Flush(); 마무리 작업 동적으로 할당했던 Carchieve와 CSocketFile 객체를 삭제 void CDataSocket::OnClose(int nErrorCode) { if(m_pFile != NULL) { delete m_pFile; m_pFile = NULL; } if(m_pArchiveIn != NULL) { m_pArchiveIn->Abort(); delete m_pArchiveIn; m_pArchiveIn = NULL; if(m_pArchiveOut != NULL) { m_pArchiveOut->Abort(); delete m_pArchiveOut; m_pArchiveOut = NULL; CSocket::OnClose(nErrorCode);

26 데이터 구조 CData 클래스 만들기 전송될 데이터는 Cdata 클래스에 캡슐화 문자열 하나를 전송
class CData : public CObject { // Attributes public: // Operations CData(); virtual ~CData(); // Overrides virtual void Serialize(CArchive &ar); CString m_strData; protected: }; void CData::Serialize(CArchive &ar) { if(ar.IsStoring()) // 네트워크로 송신 ar << m_strData; } else // 네트워크에서 수신 ar >> m_strData;

27 기타 함수들 virtual int Send( const void* lpBuf, int nBufLen, int nFlags = 0 ); 리턴값:송신한 바이트 수 lpBuf: 송신할 데이터가 저장되어 있는 버퍼의 포인터 nBufLen: 송신할 데이터의 바이트 수 nFlag: 이 함수가 호출 되는 방식 virtual int Receive( void* lpBuf, int nBufLen, int nFlags = 0 ); BOOL Listen( int nConnectionBacklog = 5 ); nConnectionBacklog : The maximum length to which the queue of pending connections can grow. Valid range is from 1 to 5. BOOL Connect( LPCTSTR lpszHostAddress, UINT nHostPort ); BOOL Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, LPCTSTR lpszSocketAddress = NULL );

28 참조 사이트 지킴이 자료실

29 Note & Q/A 강의 일정 프로젝트 제안서 제출 ( 2인 1조 ) 프로젝트 최종 보고서 제출 10월 27일 11월 3일
중간고사기간 (10월 17일 ~ 1주간)이후 11월 10일까지(실습 3 진행한 다음주까지) 프로젝트 최종 보고서 제출 12월 1일오후 6시부터 컴퓨터실 공업센타 별관 - PC 2실 611호


Download ppt "범용 소켓 클래스 만들기."

Similar presentations


Ads by Google