티스토리 뷰

Visual Studio 2012


멀티 스레드를 사용하여 소켓통신용 서버 프로그램을 만들어보자.


기존에 만들었던 소켓통신 채팅 서버프로그램에서 몇가지 수정하고 추가하면 된다.



1. CWinThread용 클래스 생성 및 구현


  • 클래스 마법사에서 'MFC 클래스' 클릭


    • 클래스 추가 - 기본클래스는 CWinThread으로 지정


    • CSocketThread 클래스

    - 필요 함수

    1. SetWnd : 다이얼로그의 핸들을 받기 위한 함수


    • 함수 및 핸들 변수 선언
      // CSocketThread.h
      //
      
      #include "ClientSocket.h"  //ClientSocket 헤더 추가
      
      #define WM_ACCEPT_SOCKET WM_USER+1  //ServerSocket에 있던 메시지 쓰레드로 이동
      
      class CSocketThread : public CWinThread
      {
      	...
      public:
      	CClientSocket m_ClientSocket;
      	SOCKET m_hSocket;
      
      	HWND m_hWnd;
      	void SetWnd(HWND hWnd);
      };


      • 함수 구현

      - 쓰레드에서 Client 매칭하는 소켓을 생성할거기 때문에 ServerSocket에 있던 Sendmessage를 이동시켰다.

      // SocketThread.cpp : 구현 파일입니다.
      //
      
      void CSocketThread::SetWnd(HWND hWnd)
      {
      	m_hWnd = hWnd;
      }
      
      BOOL CSocketThread::InitInstance()
      {
      	// TODO: 여기에서 각 스레드에 대한 초기화를 수행합니다.
      	// 리슨 소켓으로부터 넘겨받은 소켓을 자신의 멤버 소켓에 붙인다.
      	m_ClientSocket.Attach(m_hSocket);
      	m_ClientSocket.m_pThread = this;
      	m_ClientSocket.SetWnd(m_hWnd);
      
      	//ServerSocket에서 활용하던 Sendmessage 이곳으로 이동
      	SendMessage(m_hWnd, WM_ACCEPT_SOCKET, 0, (LPARAM)&m_ClientSocket);
      	return TRUE;
      }


      2. Client 매칭 소켓 클래스


      • 변수 추가 : 쓰레드 관련 변수 추가한다.
        // ClientSocket.h : 헤더 파일입니다.
        //
        
        class CClientSocket : public CSocket
        {
        public:
        	...
        	//Thread
        	CWinThread *m_pThread;
        };


        • 소스 추가

        - OnClose()에 소켓 소멸시 쓰레드로 CLOSE 메시지 보내는 구문 추가

        // ClientSocket.cpp : 구현 파일입니다.
        //
        
        void CClientSocket::OnClose(int nErrorCode)
        {
        	// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
        	m_pThread->PostThreadMessage(WM_QUIT, 0, 0);
        
        	SendMessage(m_hWnd, WM_CLIENT_CLOSE, 0, (LPARAM)this);
        	
        	CSocket::OnClose(nErrorCode);
        }


        3. Listen 소켓 클래스


        • OnAccept 소스 수정(기존과 완전 달라짐)

        - 쓰레드 클래스에서 Client 매칭 소켓을 생성할거기 때문에 쓰레드 클래스의 인자를 포인터로 받아와서 쓰레드 실행 구문을 넣음.

        - CSocket형 변수를 만들고 쓰레드 안에 만든 소켓과 Detach를 통해 매칭시킨다.

          // ServerSocket.cpp : 구현 파일입니다.
          //
          
          #include "SocketThread.h"  //스레드 클래스 헤더 추가
          
          void CServerSocket::OnAccept(int nErrorCode)
          {
          	// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
          	CSocket soc;
          	if(Accept(soc))
          	{
          		CSocketThread *pThread = (CSocketThread *)AfxBeginThread(RUNTIME_CLASS(CSocketThread),
          				THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
          		pThread->SetWnd(m_hWnd);
          
          		if(!pThread)
          		{
          			soc.Close();
          			AfxMessageBox(_T("ERROR : Thread could not be created."));
          			return;
          		}
          
          		//연결되면 클라이언트쪽에 메시지 보냄
          		soc.Send(_T("Connected with Server"),43);
          
          		// 접속한 소켓을 분리해서 소켓의 핸들을 스레드에게 넘겨준다
          		pThread->m_hSocket = soc.Detach();
          		// 생성한 스레드를 실행시킨다
          		pThread->ResumeThread();
          	}
          
          	CSocket::OnAccept(nErrorCode);
          }


          소스코드 참조 : https://winx.kr/UdrpJd4qr5

          댓글