ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [MFC] PC <-> PC 소켓 통신 TCP/IP / 이더넷 연결 / 무선 연결 / IP 통신 / JSON / rapid JSON
    정보공유/공부 2024. 1. 2. 10:25

    개요

    소켓 연결 윈도우
    메인 윈도우

    목적 Pc 두대 이더넷 연결을 통해 데이터 주고 받는 코드 구현
    (Soket 통신 TCP/IP)
    환경 노트북 2LAN 선으로 연결
    프로그램주요 내용 피시1을 서버로 만들고 피시2에서 클라이언트로 접속하여 데이터를 주고 받을 수 있도록 구현
    + Json 형식 데이터에서 원하는 값 추출

     

     

    통신 순서 이미지
    통신 순서

    통신 순서는 이렇게 진행이 된다. 서버에서 소켓을 오픈을 하면 연결 대기 (Listen) 하다가 클라이언트에서 연결(Connect)시도를 하면 허락을 한 뒤 데이터 수송신이 이뤄진다.

     

    소켓 통신 기본 설정 - CSocket

    ‘Csocket’ : base class undefined 발생 시 소켓통신을 하기 위해서는 CSocket 이라는 클래스가 필요한데 초기 프로그램 생성시 window socket 체크를 해주던가 체크를 안해주었으면 프로그램 내 StdAfx.h 혹은 Pch.h에 afxsock.h를 참조해 주면 된다

     

    Main 코드

    기본 클래스 : CWnd

    GUI 구현을 위한 메인창의 코드입니다.

    main.cpp

    // CmmuniCationView.cpp: CCmmuniCationView 클래스의 구현
    //
    
    #include "pch.h"
    #include "framework.h"
    // SHARED_HANDLERS는 미리 보기, 축소판 그림 및 검색 필터 처리기를 구현하는 ATL 프로젝트에서 정의할 수 있으며
    // 해당 프로젝트와 문서 코드를 공유하도록 해 줍니다.
    #ifndef SHARED_HANDLERS
    #include "CmmuniCation.h"
    #endif
    
    #include "CmmuniCationDoc.h"
    #include "CmmuniCationView.h"
    
    #include "ServerSock.h"
    #include "ClientSock.h"
    
    // json 데이터
    #include "rapidjson/document.h"
    
    using namespace rapidjson;
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    
    
    // CCmmuniCationView
    
    IMPLEMENT_DYNCREATE(CCmmuniCationView, CFormView)
    
    BEGIN_MESSAGE_MAP(CCmmuniCationView, CFormView)
    	ON_MESSAGE(UM_CLIENT_ACCEPT, onAccept)
    	ON_MESSAGE(UM_DATA_RECEIVE, onReceve)
    	ON_BN_CLICKED(IDC_BUTTON_IP_ADD, &CCmmuniCationView::OnBnClickedButtonIpAdd)
    	ON_BN_CLICKED(IDC_BUTTON_SEND_DATA, &CCmmuniCationView::OnBnClickedButtonSendData)
    	ON_BN_CLICKED(IDC_RADIO_RS232, &CCmmuniCationView::OnBnClickedRadioRs232)
    	ON_BN_CLICKED(IDC_RADIO_RS485, &CCmmuniCationView::OnBnClickedRadioRs485)
    	ON_BN_CLICKED(IDC_RADIO_IP, &CCmmuniCationView::OnBnClickedRadioIp)
    	ON_BN_CLICKED(IDC_BUTTON_IP_ADD2, &CCmmuniCationView::OnBnClickedButtonIpAdd2)
    END_MESSAGE_MAP()
    
    // CCmmuniCationView 생성/소멸
    
    CCmmuniCationView::CCmmuniCationView() noexcept
    	: CFormView(IDD_CMMUNICATION_FORM)
    	, m_edit_Ip_Add(_T("127.0.0.1"))
    	, m_edit_SendData(_T(""))
    	, m_edit_ReplyData(_T(""))
    	, m_static_Lot(_T(""))
    	, m_static_Dblink(_T(""))
    	, m_static_Client_Ip(_T("접속 대기 중 .."))
    	, IP_Addr(0)
    	, m_Radio(0)
    	, m_btnServer(false)
    {
    	// TODO: 여기에 생성 코드를 추가합니다.
    
    }
    
    CCmmuniCationView::~CCmmuniCationView()
    {
    }
    
    LRESULT CCmmuniCationView::onAccept(WPARAM wParam, LPARAM lParam)
    {
    	m_static_Client_Ip = m_serverSock.strClientIPAddress;
    	m_static_Client_Ip += L" 접속 중";
    	UpdateData(false);
    	return 0;
    }
    
    LRESULT CCmmuniCationView::onReceve(WPARAM wParam, LPARAM lParam)
    {
    	wchar_t* pBuffer = (wchar_t*)wParam;
    	m_edit_ReplyData.Format(L"%s", pBuffer);
    	
    	char* pszBuff;// rapidjson 관련 함수 사용시 char 형을 써야함
    	int strSize = WideCharToMultiByte(CP_ACP, 0, pBuffer, -1, NULL, 0, NULL, NULL); // wchar_t 변수 길이 구하기
    
    	pszBuff = new char[strSize];
    	memset(pszBuff, 0, sizeof(pszBuff));// char 변수 초기화
    
    	WideCharToMultiByte(CP_ACP, 0, pBuffer, -1, pszBuff, strSize, 0, 0); // wchar_t -> char 에 문자 넣어 주기
    
    	Document doc;
    	doc.Parse(pszBuff);
    	const char* findKey1 = "";
    	const char* findKey2 = "LOT";
    
    	if (doc.IsObject()) // 제이슨 형식인가
    	{	
    		Value& v = doc;
    		if (v.HasMember(findKey1)) // 해당 멤버가 있는지 확인 
    			m_static_Dblink = CA2T(v["DBLINK"].GetString(), CP_UTF8);
    		if (v.HasMember(findKey2))
    			m_static_Lot = CA2T(v["LOT"].GetString(), CP_UTF8);		
    	}
    	UpdateData(false);
    	return 0;
    }
    
    void CCmmuniCationView::DoDataExchange(CDataExchange* pDX)
    {
    	CFormView::DoDataExchange(pDX);
    	DDX_Text(pDX, IDC_EDIT_IP_ADD, m_edit_Ip_Add);
    	DDX_Text(pDX, IDC_EDIT_SEND_DATA, m_edit_SendData);
    	DDX_Text(pDX, IDC_EDIT_REPLY_DATA, m_edit_ReplyData);
    	DDX_Text(pDX, IDC_STATIC_LOT, m_static_Lot);
    	DDX_Text(pDX, IDC_STATIC_DBLINK, m_static_Dblink);
    	DDX_Text(pDX, IDC_STATIC_Client_Ip, m_static_Client_Ip);
    	DDX_IPAddress(pDX, IDC_IPADDRESS, IP_Addr);
    	DDX_Radio(pDX, IDC_RADIO_IP, m_Radio);
    	DDX_Control(pDX, IDC_STATIC_INFO, m_static_Info);
    	DDX_Control(pDX, IDC_COMBO, m_combo);
    }
    
    BOOL CCmmuniCationView::PreCreateWindow(CREATESTRUCT& cs)
    {
    	// TODO: CREATESTRUCT cs를 수정하여 여기에서
    	//  Window 클래스 또는 스타일을 수정합니다.
    
    	return CFormView::PreCreateWindow(cs);
    }
    
    void CCmmuniCationView::OnInitialUpdate()
    {
    	CFormView::OnInitialUpdate();
    	GetParentFrame()->RecalcLayout();
    	ResizeParentToFit();
    
    	wchar_t comNum[MAX_BUFF];
    
    	for (int i = 1; i <= 20; i++)
    	{
    		swprintf_s(comNum, MAX_BUFF, L"COM %d", i);
    		m_combo.AddString(comNum);
    	}
    
    	GetDlgItem(IDC_COMBO)->ShowWindow(false);
    
    
    }
    
    
    // CCmmuniCationView 진단
    
    #ifdef _DEBUG
    void CCmmuniCationView::AssertValid() const
    {
    	CFormView::AssertValid();
    }
    
    void CCmmuniCationView::Dump(CDumpContext& dc) const
    {
    	CFormView::Dump(dc);
    }
    
    CCmmuniCationDoc* CCmmuniCationView::GetDocument() const // 디버그되지 않은 버전은 인라인으로 지정됩니다.
    {
    	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CCmmuniCationDoc)));
    	return (CCmmuniCationDoc*)m_pDocument;
    }
    #endif //_DEBUG
    
    
    // CCmmuniCationView 메시지 처리기
    
    
    void CCmmuniCationView::OnBnClickedButtonIpAdd()
    {
    	UpdateData(true);
    	if(m_Radio == 0)
    	{
    		if (m_clientSock.m_bIsConnect)
    		{
    			GetDlgItem(IDC_BUTTON_IP_ADD)->SetWindowText(L"Ok");
    			m_clientSock.CloseClientSocket();
    		}
    
    		else
    		{
    			CString str_IP_Addr;
    			str_IP_Addr.Format(L"%lu", IP_Addr);
    			m_clientSock.Init(this, str_IP_Addr);
    			if (m_clientSock.m_bIsConnect)
    				GetDlgItem(IDC_BUTTON_IP_ADD)->SetWindowText(L"Exit");
    
    		}
    		m_edit_ReplyData = L"";
    		m_edit_SendData = L"";
    		UpdateData(false);
    	}
    	else
    	{
    		if (m_combo.GetCurSel() > 9)
    		{
    		}
    	}
    }
    
    void CCmmuniCationView::OnBnClickedButtonSendData()
    {
    	UpdateData(true);
    
    	if (m_clientSock.m_bIsConnect)
    	{
    		UpdateData(true);
    		m_clientSock.SendToServer(m_edit_SendData);
    		m_edit_ReplyData = L"";
    		UpdateData(false);
    	}
    	else
    	{
    		m_serverSock.SendToClient(m_edit_SendData);
    	}
    }
    
    void CCmmuniCationView::OnBnClickedRadioIp()
    {
    	GetDlgItem(IDC_COMBO)->ShowWindow(false);
    	GetDlgItem(IDC_IPADDRESS)->ShowWindow(true);
    	GetDlgItem(IDC_STATIC_INFO)->SetWindowText(L"IP Address : ");
    	GetDlgItem(IDC_BUTTON_SERVER)->ShowWindow(true);
    }
    
    void CCmmuniCationView::OnBnClickedRadioRs232()
    {
    	GetDlgItem(IDC_IPADDRESS)->ShowWindow(false);
    	GetDlgItem(IDC_COMBO)->ShowWindow(true);
    	GetDlgItem(IDC_STATIC_INFO)->SetWindowText(L"Port : ");
    	GetDlgItem(IDC_BUTTON_SERVER)->ShowWindow(false);
    
    	m_combo.SetCurSel(0);
    }
    
    void CCmmuniCationView::OnBnClickedRadioRs485()
    {
    	GetDlgItem(IDC_IPADDRESS)->ShowWindow(false);
    	GetDlgItem(IDC_COMBO)->ShowWindow(true);
    	GetDlgItem(IDC_STATIC_INFO)->SetWindowText(L"Port : ");
    	GetDlgItem(IDC_BUTTON_SERVER)->ShowWindow(false);
    
    	m_combo.SetCurSel(0);
    
    }
    
    
    
    void CCmmuniCationView::OnBnClickedButtonIpAdd2()
    {
    	if (!m_btnServer)
    	{
    		m_serverSock.Init(this);
    		m_btnServer = true;
    
    		GetDlgItem(IDC_IPADDRESS)->EnableWindow(false);
    		GetDlgItem(IDC_COMBO)->EnableWindow(false);
    		GetDlgItem(IDC_BUTTON_IP_ADD)->EnableWindow(false);
    	}
    	else
    	{
    		m_serverSock.CloseServerSocket();
    		m_btnServer = false;
    
    		GetDlgItem(IDC_IPADDRESS)->EnableWindow(true);
    		GetDlgItem(IDC_COMBO)->EnableWindow(true);
    		GetDlgItem(IDC_BUTTON_IP_ADD)->EnableWindow(true);
    
    		m_static_Client_Ip = L"대기 중";
    	}
    	
    	UpdateData(false);
    }

     

    main.h

    // CmmuniCationView.h: CCmmuniCationView 클래스의 인터페이스
    
    #pragma once
    
    #include "afxwin.h"
    #include "afxcmn.h"
    #include "ServerSock.h"
    #include "ClientSock.h"
    
    class CCmmuniCationView : public CFormView
    {
    protected: // serialization에서만 만들어집니다.
    	CCmmuniCationView() noexcept;
    	DECLARE_DYNCREATE(CCmmuniCationView)
    
    public:
    #ifdef AFX_DESIGN_TIME
    	enum{ IDD = IDD_CMMUNICATION_FORM };
    #endif
    
    // 특성입니다.
    public:
    	CCmmuniCationDoc* GetDocument() const;
    
    // 작업입니다.
    public:
    
    	CClientSock m_clientSock;
    	CServerSock m_serverSock;
    
    
    
    // 재정의입니다.
    public:
    	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
    protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 지원입니다.
    	virtual void OnInitialUpdate(); // 생성 후 처음 호출되었습니다.
    
    // 구현입니다.
    public:
    	virtual ~CCmmuniCationView();
    #ifdef _DEBUG
    	virtual void AssertValid() const;
    	virtual void Dump(CDumpContext& dc) const;
    #endif
    
    protected:
    
    // 생성된 메시지 맵 함수
    protected:
    	DECLARE_MESSAGE_MAP()
    public:
    	bool m_bServerReadyFlag;
    	bool m_bServerResetFlag;
    	CString m_edit_Ip_Add;
    	CString m_edit_SendData;
    	CString m_edit_ReplyData;
    
    	LRESULT onReceve(WPARAM wParam, LPARAM lParam);
    	LRESULT onAccept(WPARAM wParam, LPARAM lParam);
    
    	afx_msg void OnBnClickedButtonIpAdd();
    	afx_msg void OnBnClickedButtonSendData();
    
    	CString m_static_Lot;
    	CString m_static_Dblink;
    	CString m_static_Client_Ip;
    	DWORD IP_Addr;
    	int m_Radio;
    	CStatic m_static_Info;
    	afx_msg void OnBnClickedRadioRs232();
    	afx_msg void OnBnClickedRadioRs485();
    	afx_msg void OnBnClickedRadioIp();
    	CComboBox m_combo;
    	afx_msg void OnBnClickedButtonIpAdd2();
    	bool m_btnServer;
    };
    
    #ifndef _DEBUG  // CmmuniCationView.cpp의 디버그 버전
    inline CCmmuniCationDoc* CCmmuniCationView::GetDocument() const
       { return reinterpret_cast<CCmmuniCationDoc*>(m_pDocument); }
    #endif

     

    SERVER 코드

    기본 클래스 : CAsyncSocket

    serverSock.cpp

    // ServerSock.cpp: 구현 파일
    
    #include "pch.h"
    #include "CmmuniCation.h"
    #include "ServerSock.h"
    #include "ClientSock.h"
    
    
    // CServerSock
    
    CServerSock::CServerSock()
    {
    	m_bIsListen = false;
    }
    
    CServerSock::~CServerSock()
    {
    }
    
    // CServerSock 멤버 함수
    
    bool CServerSock::Init(CWnd* pWnd)
    {
    	if (m_bIsListen)	return false;
    
    	m_pWnd = pWnd; // 소켓 클래스와 메인 윈도우 연결
    
    	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    	{
    		AfxMessageBox(L"WSAStartup() Error");
    		return false;
    	}
    
    	if (Create(SERVER_PORT_NUMBER)) // 연결하려는 포트로 서버를 생성 (Creat 함수 안에 bind 함수가 있음)        Bind : 아이피와 포트를 묶음
    	{
    		if (!Listen()) //연결을 받아들일 소켓 : 클라이언트는 connect를 호출해 연결을 시도
    		{
    			AfxMessageBox(_T("ListenSocket ERROR : Listen() returns FALSE!"));
    			return false;
    		}
    	}
    	else
    	{
    		AfxMessageBox(_T("ListenSocket ERROR : Failed to create listen socket!"));
    		return false;
    	}
    
    	AfxMessageBox(_T("SERVER OPEN"));
    	m_bIsListen = true;
    	return true;
    }
    
    
    void CServerSock::OnAccept(int nErrorCode) //클라이언트에서 접속 요청이 오면 OnAccept 함수 호출
    {
    	CClientSock* pClient = new CClientSock; //연결 소켓 생성
    	//	if (accept(client_sock, (SOCKADDR *)&clientaddrv4,&addrlen))
    	if (Accept(*pClient)) //만들어진 연결 소켓을 이용해 클라이언트와 통신
    	{
    		
    		UINT nClientPortNum;
    		pClient->GetPeerName(strClientIPAddress, nClientPortNum); //클라이언트 IP주소 및 포트 정보를 얻음
    
    		pClient->Init(m_pWnd, (CAsyncSocket*)this);
    
    		m_ptrClientSocketList.AddTail(pClient); //서버에 연결된 클라이언트 리스트에 리스트업
    
    		pClient->m_bIsConnect = true;
    		
    		m_pWnd->SendMessage(UM_CLIENT_ACCEPT); //유저 메세지 호출
    	}
    	else
    	{
    		delete pClient;
    		AfxMessageBox(_T("ListenSocket ERROR : Failed to accept new client!"));
    	}
    
    
    	CAsyncSocket::OnAccept(nErrorCode);
    }
    
    void CServerSock::CloseServerSocket(void) //서버에서 소켓을 닫을 때
    {
    	if (m_bIsListen)
    	{
    		POSITION pos;
    		pos = m_ptrClientSocketList.GetHeadPosition();
    		if (pos != 0)
    		{
    			CClientSock* pDataSocket = NULL;
    
    			while (pos)
    			{
    				pDataSocket = (CClientSock*)m_ptrClientSocketList.GetNext(pos); //클라이언트 목록을 돌면서 하나씩 닫아준다.
    				if (pDataSocket)
    				{
    					pDataSocket->ShutDown();
    					pDataSocket->Close();
    
    					delete pDataSocket;
    				}
    			}
    		}
    
    		ShutDown();
    		Close();
    
    		WSACleanup();
    
    		m_bIsListen = false;
    	}
    }
    
    void CServerSock::OnCloseClientSocket(CSocket* pClientSocket) //클라이언트에서 접속을 끊었을 때
    {
    	POSITION pos;
    	pos = m_ptrClientSocketList.Find((CClientSock*)pClientSocket); //클라이언트 목록에서 연결이 끊어진 클라이언트를 찾음
    
    	if (pos) //연결이 끊어진 클라이언트 목록에서 제거 및 연결 소켓 삭제
    	{
    		m_ptrClientSocketList.RemoveAt(pos);
    		delete pClientSocket; 
    	}
    }
    
    
    
    bool CServerSock::SendToClient(CString strMessage) //서버에서 클라이언트에 데이터 전송 시 호출
    {
    	if (m_ptrClientSocketList.GetCount() == 0) return false;
    
    	POSITION pos;
    	pos = m_ptrClientSocketList.GetHeadPosition();
    	CClientSock* pClient = NULL;
    
    	
    	pClient = (CClientSock*)m_ptrClientSocketList.GetNext(pos);
    
    	if (pClient != NULL) {
    		// Send함수의 두번째 인자는 메모리의 크기인데 유니코드를 사용하고 있으므로 *2를 한 크기가 된다.
    		// 이 함수는 전송한 데이터의 길이를 반환한다.
    		int checkLenOfData = pClient->Send(strMessage, strMessage.GetLength() * sizeof(wchar_t));
    
     		if (checkLenOfData != lstrlen(strMessage) * 2) {
     			AfxMessageBox(_T("일부 데이터가 정상적을 전송되지 못했습니다!"));
     			return false;
     		}
    
    		delete pClient;
    	}
    
    	return true;
    
    }

     

    serversock.h

    #pragma once
    
    
    // CServerSock 명령 대상
    #define UM_CLIENT_ACCEPT	(WM_USER+100)
    //#define SERVER_IP_ADDRESS	_T("127.0.0.1")
    #define SERVER_PORT_NUMBER	5000
    
    
    
    #define STRING_LENGTH		255
    
    
    
    class CServerSock : public CAsyncSocket
    {
    public:
    	CServerSock();
    	virtual ~CServerSock();
    
    	WSADATA wsaData;												//Socket 사용을 알리는 함수
    	CWnd* m_pWnd;
    	CPtrList m_ptrClientSocketList;									//Client 리스트
    	bool m_bIsListen;												//Listen 상태확인 Flag
    	CString strClientIPAddress;
    
    	bool Init(CWnd* pWnd);
    	virtual void OnAccept(int nErrorCode);
    	void CloseServerSocket(void);
    	void OnCloseClientSocket(CSocket* pDataSocket);
    	bool SendToClient(CString strMessage);
    };

     

     

    CLIENT 코드

    기본 클래스 : CSocket

    clientSock.cpp

    // ClientSock.cpp: 구현 파일
    //
    
    #include "pch.h"
    #include "ClientSock.h"
    #include "ServerSock.h"
    
    
    CString Addr;
    // CClientSock
    
    CClientSock::CClientSock()
    {
    	m_pServerSocket = NULL;
    	m_pBuffer = NULL;
    	m_bIsConnect = false;
    
    	m_pBuffer = new wchar_t[BUFFER_LENGTH];
    	Addr = L"127.0.0.1";
    }
    
    CClientSock::~CClientSock()
    {
    	delete[] m_pBuffer;
    }
    
    
    // CClientSock 멤버 함수
    
    bool CClientSock::Init(CWnd* pWnd, CString strAddr, CAsyncSocket* pServerSocket)
    {
    	if (m_bIsConnect)
    		return false;
    	Addr = strAddr;
    	m_pWnd = pWnd;
    	m_pServerSocket = pServerSocket;
    
    	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 		                                           
    	{	// WSAStartup : WSACleanup 함수와 쌍을 이뤄 소켓 프로그램의 시작과 끝을 나타냄 
    		// 윈속 동적 연결 라이브러리를 초기화하고 윈속 구현이 애플리케이션 요구사항을 충족하는지 확인
    		AfxMessageBox(L"WSAStartup() Error");
    		return false;
    	}
    
    	if (!m_pServerSocket)
    	{
    		Create(); // 클라이언트 생성
    		m_pWnd->SetTimer(CONNECT_TIMEER, 1000, NULL); // Timer 아이디 CONNECT_TIMEER, 시간간격 5초의 타이머 설치
    		if (!Connect(Addr, SERVER_PORT_NUMBER))			//서버와 연결
    		{
    			m_pWnd->KillTimer(CONNECT_TIMEER);
    			AfxMessageBox(_T("연결 시간 초과"), MB_OK | MB_ICONINFORMATION);
    			m_pWnd = NULL;
    			m_pServerSocket = NULL;
    			ShutDown();
    			Close();
    
    			return false;
    		}
    		else
    		{
    			m_pWnd->KillTimer(CONNECT_TIMEER);
    			AfxMessageBox(_T("Successfully connected to Server"), MB_OK | MB_ICONINFORMATION);
    
    			memset(m_pBuffer, 0, sizeof(wchar_t) * BUFFER_LENGTH);
    		}
    	}	
    
    	m_bIsConnect = true;
    
    	return true;
    }
    
    bool CClientSock::Init(CWnd* pWnd, CAsyncSocket* pServerSocket)
    {
    	if (m_bIsConnect)
    	{
    		AfxMessageBox(_T("서버와 연결 확인 요망"));
    		return false;
    	}
    
    	m_pWnd = pWnd;
    	m_pServerSocket = pServerSocket;
    
    	if (!m_pServerSocket)
    	{
    		Create();
    		m_pWnd->SetTimer(CONNECT_TIMEER, 1000, NULL); // Timer 아이디 CONNECT_TIMEER, 시간간격 5초의 타이머 설치
    		if (!Connect(Addr, SERVER_PORT_NUMBER))			//서버와 연결
    		{
    			m_pWnd->KillTimer(CONNECT_TIMEER);
    			m_pWnd = NULL;
    			m_pServerSocket = NULL;
    			ShutDown();
    			Close();
    
    			return false;
    		}
    		else {
    			m_pWnd->KillTimer(CONNECT_TIMEER);
    		}
    	}
    
    	memset(m_pBuffer, 0, sizeof(wchar_t) * BUFFER_LENGTH);
    
    	m_bIsConnect = true;
    
    	return true;
    }
    
    
    bool CClientSock::SendToServer(CString strMessage)
    {
    	if (!m_bIsConnect)
    	{
    		AfxMessageBox(_T("서버와 연결 확인 요망"));
    		return false;
    	}
    
    	if (Send(strMessage, strMessage.GetLength() * sizeof(wchar_t)) == strMessage.GetLength() * sizeof(wchar_t))
    		return true;
    	else
    		return false;
    }
    
    bool CClientSock::SendToServer(wchar_t* wstrMessage)
    {
    	if (!m_bIsConnect)
    	{
    		AfxMessageBox(_T("서버와 연결 확인 요망"));
    		return false;
    	}
    
    	if (Send((LPVOID)(LPCTSTR)wstrMessage, (int)wcslen(wstrMessage) * sizeof(wchar_t)) == (int)wcslen(wstrMessage) * sizeof(wchar_t))
    		return true;
    	else
    		return false;
    }
    
    void CClientSock::OnReceive(int nErrorCode)
    {
    	int iLen = 0;
    	memset(m_pBuffer, 0, sizeof(wchar_t) * BUFFER_LENGTH);
    
    	if (Receive(m_pBuffer, sizeof(wchar_t) * BUFFER_LENGTH) > 0)
    	{
    		iLen = (int)wcslen(m_pBuffer);
    		m_pWnd->SendMessage(UM_DATA_RECEIVE, (WPARAM)m_pBuffer);
    	}
    
    
    	CSocket::OnReceive(nErrorCode);
    }
    
    
    void CClientSock::OnClose(int nErrorCode)
    {
    	CloseClientSocket();
    
    	m_pWnd->SendMessage(UM_DATASOCKET_CLOSE);
    
    	m_bIsConnect = false;
    
    	CSocket::OnClose(nErrorCode);
    
    	// if Server Data Socket, Delete it from List of ListenSocket, Delete this Object
    	if (m_pServerSocket)
    		((CServerSock*)m_pServerSocket)->OnCloseClientSocket((CSocket*)this);
    
    	CSocket::OnClose(nErrorCode);
    }
    
    
    void CClientSock::CloseClientSocket()
    {
    	if (m_bIsConnect)
    	{
    		ShutDown();
    		Close();
    
    		WSACleanup();
    
    		m_bIsConnect = false;
    	}
    }
    
    
    BOOL CClientSock::OnMessagePending()
    {
    	MSG msg;
    	if (PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE))
    	{ 
    		if (msg.message == CONNECT_TIMEER) {
    			PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
    			CancelBlockingCall();
    			Close();
    		} 
    	}
    
    
    	return CSocket::OnMessagePending();
    }

     

    clientSock.h

    #pragma once
    
    // CClientSock 명령 대상
    // CClientSocket 명령 대상입니다.
    #define UM_DATA_RECEIVE		(WM_USER+901)
    #define UM_DATASOCKET_CLOSE	(WM_USER+902)
    #define BUFFER_LENGTH		(1024*1024)
    
    class CClientSock : public CSocket
    {
    public:
    	CClientSock();
    	virtual ~CClientSock();
    	HWND m_hWnd;
    	WSADATA wsaData;												//Socket 사용을 알리는 함수
    	CWnd* m_pWnd;
    	CAsyncSocket* m_pServerSocket;									//Server Socket 연결에 사용할 포인터
    	wchar_t* m_pBuffer;												//Server에 보낼 메세지 데이터
    	bool m_bIsConnect;												//Server와 Client와의 연결 확인 Flag
    
    	bool Init(CWnd* pWnd, CString strAddr, CAsyncSocket* pServerSocket = NULL);
    	bool Init(CWnd* pWnd, CAsyncSocket* pServerSocket = NULL);		//ClientSocket Init & ServerSocket 연결
    
    	virtual void OnReceive(int nErrorCode);
    	virtual void OnClose(int nErrorCode);
    	void CloseClientSocket();
    	bool SendToServer(CString strMessage);							//Server에 Message를 보냄
    	bool SendToServer(wchar_t* wstrMessage);							//Server에 Message를 보냄
    
    	virtual BOOL OnMessagePending();
    };

     

    댓글

Designed by Tistory.