1. MFC 윈도우 콘솔 응용프로그램을 2개 만든다. (TCPServer1, TCPClient1)
1개는 서버
1개는 클라이언트
2. 2개의 프로젝트에 있는 미리컴파일되는 헤더인 stdafx.h에 소켓사용을 위해서
#include <afxsock.h> 를 추가해준다.
3. TCPServer1.cpp의 코드
// TCPServer1.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.//#include "stdafx.h"#include "TCPServer1.h"#ifdef _DEBUG#define new DEBUG_NEW#endifCWinApp theApp;using namespace std;void ErrQuit(int err) { //에러를 처리하는 함수LPVOID lpMsgBuf;FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL, err,MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),(LPTSTR)&lpMsgBuf, 0, NULL);MessageBox(NULL, (LPCTSTR)lpMsgBuf, _T("오류발생"), MB_ICONERROR);LocalFree(lpMsgBuf);exit(1);}int main(){int nRetCode = 0;HMODULE hModule = ::GetModuleHandle(nullptr);if (hModule != nullptr){if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0)){wprintf(L"심각한 오류: MFC를 초기화하지 못했습니다.\n");nRetCode = 1;}else{// TODO: 응용 프로그램의 동작은 여기에서 코딩합니다._tsetlocale(LC_ALL, _T("")); //C++에서 io를 할때, 경로명이나 파일명에 한글이 포함되면 오작동의 위험이있다.//그래서 locale를 변경 해줘서 지역을 업데이트 해준다. 우리나라에서 하면 _tsetlocale(LC_ALL, _T("Korean"));효과가 있을것이다.AfxSocketInit(); //소켓 사용을 위해 관련된 것들을 초기화 시켜줌.CSocket sock; // 소켓변수선언if (!sock.Create(8000)) { //포트 8000의 socket을 생성한다.//실패하면 0을 반환해서 에러뜨게함.ErrQuit(sock.GetLastError()); // GetLastError()는 호출된 스레드의 마지막 오류 코드값 반환}if (!sock.Listen()) { // 클라이언트의 접속요청을 확인하는 상태로 변경ErrQuit(sock.GetLastError());}TCHAR buf[256+1];int nbytes;while(1){ // 무한정 대기CSocket newsock;if (!sock.Accept(newsock)) { //클라이언트의 접속을 기다리다가(대기), 요청이오면 허락(승인)하고//그 클라이언트와의 통신을 위해 new socket 만듬//실패하면 에러함수 호출ErrQuit(sock.GetLastError());}CString PeerAddress;UINT PeerPort;newsock.GetPeerName(PeerAddress, PeerPort); // 지금 연결된 클라이언트와 연결을 담당하는 newsock으로 부터,//클라이언트의 주소와 포트얻기._tprintf(_T("### IP주소: %s, 포트 번호: %d ###\n"), (LPCTSTR)PeerAddress, PeerPort); // 정보출력while (1) {nbytes = newsock.Receive(buf, 256); // 현재 연결된 클라이언트와의 통신을 담당하는 newsock이 계속 정보를 받게한다.//받은정보는 buf에 256만큼 수신한다.//Receive()는 받은 데이터의 길이를 반환한다.//클라이언트쪽에서 아무것도 안보내도 0을 반환한다.if (nbytes == 0 || nbytes == SOCKET_ERROR) { // 받았는데 길이가 0이거나 에러메세지면 그만 수신한다.break;}else { // 1이상의 데이터를 받아왔으면buf[nbytes] = _T('\0'); // buf에서 nbyte번째에 해당하는곳에 \0을 붙여준다. char*문자열형에서는 끝에 \0를 붙여주는 것이 안전하다._tprintf(_T("%s"), buf); //출력한다. Client쪽에서 ?번째 테스트 메세지 라고 메세지를 전송할 것이다}}newsock.Close(); //newsock이 클라이언트와 작업이 다 끝났으면 소켓종료_tprintf(_T("### 접속종료 ###\n\n"));}}}else{wprintf(L"심각한 오류: GetModuleHandle 실패\n");nRetCode = 1;}return nRetCode;}4. TCPClient.cpp 코드// TCPClient1.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.//#include "stdafx.h"#include "TCPClient1.h"#ifdef _DEBUG#define new DEBUG_NEW#endifCWinApp theApp;using namespace std;void ErrQuit(int err) { //에러를 처리하는 함수.LPVOID lpMsgBuf;FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL, err,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR)&lpMsgBuf, 0, NULL);MessageBox(NULL, (LPCTSTR)lpMsgBuf, _T("오류발생"), MB_ICONERROR);LocalFree(lpMsgBuf);exit(1);}int main(){int nRetCode = 0;HMODULE hModule = ::GetModuleHandle(nullptr);if (hModule != nullptr){if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0)){wprintf(L"심각한 오류: MFC를 초기화하지 못했습니다.\n");nRetCode = 1;}else{// TODO: 응용 프로그램의 동작은 여기에서 코딩합니다._tsetlocale(LC_ALL, _T(""));AfxSocketInit();CSocket sock;if (!sock.Create()) { // 소켓하나 만든다.ErrQuit( sock.GetLastError() );}if (!sock.Connect(_T("127.0.0.1"), 8000)) { // 해당 IP주소에 8000포트로 연결을 시도한다.ErrQuit(sock.GetLastError());}TCHAR buf[256];int nbytes;for (int i = 0; i < 5; ++i) { // 총5개 메세지 보낼거임.wsprintf(buf, _T("%d번째 테스트 메세지\r\n"), i); // 보낼메세지를 출력도하고 buf에도 저장한다.nbytes = sock.Send(buf, 256); //sock을 통해서 256의 buf메세지를 보내고, 길이 반환.if (nbytes == SOCKET_ERROR) { // 에러메세지나오면 에러.ErrQuit(sock.GetLastError());}else { //아니면 지금 단계와, 몇바이트보냈는지 출력_tprintf(_T("<%d> %d바이트 전송\n"), i, nbytes);Sleep(1000); //1초대기}}sock.Close(); //5번다했으면 scok닫기}}else{wprintf(L"심각한 오류: GetModuleHandle 실패\n");nRetCode = 1;}return nRetCode;}5. 최종결과
'개발 > MFC programming' 카테고리의 다른 글
대화상자 기반 계산기 (0) | 2019.04.09 |
---|---|
표준 컨트롤을 통한 텍스트 입력 (0) | 2019.04.02 |
temp (0) | 2019.03.20 |
MFC programming 정의 및 세팅 (0) | 2019.03.06 |