2013.07.05 11:29


어째뜬...

MFC를 이용한 채팅 프로그램 시작하기(클라이언트편)를 시작해 보도록 하겠습니다.

그럼 서버 프로그램에 이어서 클라이언트 프로그램을 만들어 서버와 클라이언트간의 동작을 확인해 보도록 하겠습니다.

클라이언트 프로그램은 다음의 작업을 수행하게 됩니다.

서버에 연결 요청을 하고 연결이 되면 서버와 데이터를 송수신합니다.


그럼 클라이언트 프로그램을 만들어 보도록 하겠습니다.

채팅 클라이언트 프로그램도 서버 프로그램과 마찬가지로 윈도우 소켓을 지원받는 대화상자 기반으로 프로젝트를 생성하겠습니다. (프로젝트명은 ChatClient로 하겠습니다.)

서버 프로그램과 마찬가지로 GUI를 구성하도록 하겠습니다.

클라이언트는 두개의 대화상자로 구성됩니다.

서버 프로그램과 비슷한 구조의 ChatClient와 서버에 접속을 요청하기 위한 IP주소를 입력받아 서버에 접속을 요청하는 대화상자로 구성됩니다.

아래 그림과 같이 채팅 클라이언트 GUI를 구성합니다.

ChatClient 대화상자의 구성이 완료되면 Connect Setting 버튼을 클릭하면 서버에 연결을 위한 IP주소를 세팅하는 대화상자를 추가하여 아래와 같이 GUI를 구성합니다.


서버와 연결을 위한 대화 상자 템플릿을 대화 상자 클래스(CConnectDlg)로 구현합니다.

서버에 연결하기 위해 서버의 IP주소를 입력받는데 입력받은 값을 저장하기 위한 변수를 선언합니다.

Connect 버튼을 누르면 호출되는 이벤트 처리기를 추가하여 서버와의 연결을 위한 서버 IP 주소를 저장합니다. 그리고 추가로 서버 IP주소를 매번 입력하지 않도록 OnInitDialog() 함수를 CConnectDlg 클래스에 재정의하여 초기화 합니다.

다음으로 ChatClient 대화 상자에서 Connect Setting 버튼을 누르면 Connect 대화상자를 호출하고 IP주소를 입력후 Connect 버튼을 눌렀을 때 서버에 연결을 요청하는 Connect함수를 호출하도록 OnBnClickConnect()와 OnBnClickedSend() 함수를 아래와 같이 재정의 합니다.

다음으로 서버와의 통신을 위해 연결 요청을 하고 데이터를 송수신하는 CSocket의 파생클래스로클라이언트 소켓을 정의 하도록 하겠습니다.

어플리케이션 클래스에 서버와의 접속을 위해서 접속을 요청하는 클라이언트 소켓을 위한 멤버 변수를 선언합니다.

생성자에 추가한 멤버 변수를 초기화 합니다.

다음으로 서버와 마찬가지로 접속과 데이터 송수신에 필요한 함수를 만들도록 하겠습니다.
필요한 함수는 다음과 같습니다.

void Connect()

서버 소켓으로 접속요청

void CleanUp()

소켓을 닫고 메모리 해제

void SendData(CString strData)

데이터 송신

void ReceiveData()

데이터 수신

void CloseChild()

자소켓 닫고 메모리 해제

함수는 아래와 같이 내용을 구현합니다.

다음으로 서버 프로그램과 마찬가지로 데이터 송수신을 위한 가상함수를 재정의 해야 합니다.
CClientSocket 클래스의 OnReceive()함수와 OnClose() 함수를 재정의 합니다.

수고하셨습니다. 모든 작업이 끝났습니다.^^
이제 프로그램을 실행시켜 서버와 클라이언트간에 접속과 데이터 송수신을 확인해 보도록 하겠습니다.
서버 프로그램이 대기 상태에 있어야 클라이언트가 접속할 수 있으니 서버 프로그램을 먼저 실행시킵니다.

서버 프로그램은 실행과 동시에 클라이언트의 요청을 기다리게 됩니다.
서버 프로그램이 정상적으로 동작하고 있으니 클라이언트 프로그램을 실행합니다.

클라이언트 프로그램을 실행하고 Connect Setting 버튼을 눌러 연결을 요청할 서버의 IP주소를 입력(루프백 주소를 사용하도록 하겠습니다.)하고 Connect 버튼을 누르면 클라이언트가 서버와 연결을 시도하게 됩니다.
서버와의 연결이 성공적으로 이루어 지면 아래와 같이 서버에 Accept Success 메시지가 나타납니다.

정상적으로 서버와 클라이언트가 연결되었습니다.
이제 서버와 클라이언트에서 메시지를 입력하고 Send 버튼을 눌러 데이터의 송수신이 이루어 지는지 확인합니다.

모든 것이 정상적으로 동작합니다.

확인하셨죠?^^

오랜시간 수고하셨습니다.
이상으로 소켓을 이용한 간단한 채팅 서버와 클라이언트를 구현해 보았습니다.




신고


Posted by injunech
2013.07.05 11:28


그럼 MFC를 이용한 채팅 프로그래밍 시작하기(서버편) - 1에 이어서 계속 진행 하도록 하겠습니다.

앞서 말씀드린대로 남은 작업은 데이터 송수신을 위한 가상함수 재정의 부분과 대화상자 클래스에서 서버 소켓을 초기화 하고 데이터를 전송하는 부분입니다.

그럼 먼저 데이터 송수신을 위한 가상함수를 재정의 하도록 하겠습니다.
먼저 서버 소켓에 재정의 해야 하는 OnAccept() 함수를 보도록 하겠습니다.
서버 소켓은 클라이언트의 요청을 기다리는 대기 상태입니다. 이 때 클라이언트는 서버 IP주소와 포트번호로 서버에 접속 요청을 위해 Connect()함수를 호출합니다. OnAccept() 함수는 사용자의 이벤트에 의해서 호출되지 않고 클라이언트 소켓의 Connect() 함수를 통해서 호출됩니다. 따라서 이 메소드는 서버 소켓에서 재정의 되어야 하고 재정의된 함수 내부에는 연결을 받아들여 이를 자소켓에 연결해 두어야 합니다.

다음은 자소켓에 재정의 해야 하는 OnReceive() 함수 입니다.
클라이언트가 데이터를 송신하기 위해 Send() 함수를 호출하게 되면 자소켓의 OnReceive() 함수가 호출됩니다. 따라서 데이터를 수신하기 위한 ReceiveData()함수를 호출하도록 함수를 재정의 해야 합니다.

마지막으로 자소켓에 재정의 해야 하는 OnClose() 함수 입니다.
클라이언트 소켓이 닫히게 되면 OnClose() 함수가 호출됩니다. 따라서 클라이언트와 연결된 자소켓을 닫고 메모리를 해제 하도록 CloseChild()함수를 호출하도록 재정의 해야 합니다.

이제 마지막 작업만을 남겨두고 있습니다.


대화상자 클래스에서 서버 소켓을 초기화 하고 데이터를 전송하는 작업입니다.

CChatServerDlg 클래스의 OnInitDialog() 함수에서 서버 소켓을 초기화 하는 InitServer() 함수를 호출하여 서버 소켓이 클라이언트의 연결 요청을 대기하도록 합니다.

다음으로 Send 버튼을 누를 때 호출되는 메시지 핸들러를 추가한 후 클라이언트로 데이터를 송신하는 SendData() 함수를 호출 하도록 합니다.

이것으로 채팅 서버 프로그램을 완성하였습니다.
이제 클라이언트 프로그램을 만들어 확인하는 일만 남았습니다.

그럼 다음시간에 클라이언트 프로그램을 만들어 간단한 채팅 테스트를 진행하도록 하겠습니다.

감사합니다.


신고


Posted by injunech
2013.07.05 11:28


이번시간에는 소켓을 이용해 간단한 채팅 프로그램을 만들어 보도록 하겠습니다.

먼저 채팅 프로그램의 서버와 클라이언트의 통신 순서를 그림을 통해 알아보도록 하겠습니다.

아래 그림을 봐주세요.

그림에서 보는바와 같이 서버와 클라이언트는 통신을 하게 됩니다.

순서를 간단히 살펴보면 다음과 같습니다.

1. 서버 프로그램에서 서버 소켓이 클라이언트의 접속을 기다립니다.
서버측에서 클라이언트의 접속을 기다리기 위해 소켓을 생성후 Listen() 함수를 실행해 클라이언트가 접속할 때까지 대기 하도록 합니다. 서버 소켓을 생성할 때 다른 응용프로그램과의 구분을 위해 특정 포트를 지정해야 합니다.(여기서는 1470번 포트를 사용하도록 하겠습니다.)

2. 클라이언트 프로그램에서 서버 소켓에 접속을 요청합니다.
서버가 Listen()함수를 실행하여 대기 상태에 있을 때 클라이언트 프로그램에서 Connect() 함수를 호출하면 접속할 수 있습니다.

3. 데이터 송수신
클라이언트가 서버와 접속에 성공하면 서버와 클라이언트는 각각 소켓 객체를 갖게 됩니다. 각각의 소켓은 데이터 송수신을 위해 사용됩니다.

그럼 위와 같은 순서로 동작하게될 채팅 프로그램을 작성해 보도록 하겠습니다.


먼저 서버 프로그램을 만들어 보겠습니다.

채팅 서버는 클라이언트의 요청을 받아줄 소켓과 실제 클라이언트와 통신을 담당할 소켓(자소켓)이 필요합니다.
CSocket의 파생 클래스에 OnAccept() 함수를 재정의 해야 합니다. 클라이언트의 연결 요청이 발생하였을 때 클라이언트와 통신을 담당할 소켓을 생성해 주는 코드를 기술하게 됩니다.
클라이언트와 통신을 담당할 자소켓 클래스 역시 CSocket의 파생 클래스여야 하고 OnReceive() 함수를 재정의 해야 합니다. 이 함수에는 클라이언트에서 데이터를 송신하면 이를 수신하는 코드를 기술하게 됩니다.

먼저 윈도우 소켓을 지원받는 프로젝트 생성을 위해 대화상자 기반으로 MFC 프로젝트를 생성합니다. (프로젝트명은 ChatServer로 하겠습니다.)

아래 그림과 같이 채팅 서버 GUI를 구성합니다.

다음으로 클라이언트의 연결 요청을 기다리며 대기하는 서버 소켓 클래스와 클라이언트와 통신을 담당하게될 자소켓을 CSocket의 파생 클래스로 정의합니다.

아래 그램과 같이 MFC 클래스 마법사를 이용해서 CServerSocket과 CChildSocket 클래스를 CSocket의 파생 클래스로 구현합니다.

다음으로 CChatServerApp 클래스에 클라이언트의 접속을 위해 대기하는 서버 소켓과 통신을 위한 자소켓을 위한 멤버 변수 아래 그림과 같이 선언합니다.

아래와 같이 생성자에 추가한 멤버 변수를 초기화 합니다.

서버 소켓과 자소켓 객체가 어플리케이션 클래스에 생성이 되었습니다.

이제 접속과 데이터 송수신에 필요한 함수를 만들도록 하겠습니다.

필요한 함수는 다음과 같습니다.

void InitServer()

서버 소켓 초기화

void CleanUp()

소켓을 닫고 메모리 해제

void SendData(CString strData)

데이터 송신

void ReceiveData()

데이터 수신

void Accept()

접속 허용

void CloseChild()

자소켓 닫고 메모리 해제

각각의 함수는 아래와 같이 내용을 구현합니다.

함수 구현까지 마쳤습니다.

이제 남은 작업은 데이터 송수신을 위한 가상함수 재정의 부분과 대화상자 클래스에서 서버 소켓을 초기화 하고 데이터를 전송하는 부분입니다.

남은 작업은 다음시간에 계속 이어가도록 하겠습니다.

감사합니다.

이글은 초보 개발자를 위한 비주얼 C++ MFC 입문과 정석용의 TCP/IP 소켓 프로그래밍 책을 참고하여 작성하였습니다.


신고


Posted by injunech
2013.07.05 11:26


서버 프로그램이 준비되었으니 클라이언트 프로그램을 구현하도록 하겠습니다.
클라이언트 프로그램은 ‘연결’ 버튼을 클릭하면 서버 프로그램에 연결하여 서버로부터 전송된 문자열을 화면에 출력하게 됩니다.

MFC로 클라이언트 프로그램을 구현할 때 다음의 순서로 진행하도록 하겠습니다.
1 응용 프로그램 마법사로 프로젝트를 만듭니다.
2 GUI를 설계하고, 각각의 컨트롤에 대해 멤버 함수와 멤버 변수를 추가하고 코딩합니다.
3 서버 프로그램과 연결해서 기능을 검증합니다.

클라이언트 프로그램을 구현하기 위해서 프로젝트를 생성하겠습니다.
대화 상자 기반으로 고급기능에서 ‘Window 소켓’을 체크하여 프로젝트를 생성합니다.
프로젝트 이름은 HelloClient로 하겠습니다.
서버 프로그램과 마찬가지 순서로 프로젝트를 생성합니다.

다음으로 GUI설계와 컨트롤에 대한 멤버 함수와 멤버 변수를 추가하도록 하겠습니다.
GUI를 다음과 같이 구성합니다.

준비가 되었으면 HelloClientDlg.h를 작성하도록 하겠습니다.

다음으로 CHelloClientDlg 클래스에서 연결 버튼을 누르면 수행하는 OnBnClickedButtonConnect 멤버 함수의 내용을 구현하도록 하겠습니다.

프로그램 구현을 모두 끝냈습니다.

이제 모든 준비가 끝났습니다.

준비된 서버 프로그램과 클라이언트 프로그램을 실행하여 잘 동작하는지 확인해 보도록 하겠습니다.

먼저 서버 프로그램을 실행합니다.

서버 프로그램이 실행되면 시작버튼을 눌러 클라이언트의 요청을 기다립니다.

소켓 생성을 성공하면 위와 같이 Socket Create Success 메시지를 출력하고 서버는 클라이언트의 연결 요청을 기다리게 됩니다.

소켓 생성을 실패한 경우 아래와 같이 메시지를 출력하게 됩니다.

서버 준비가 완료되면 클라이언트 프로그램을 실행합니다.

클라이언트 프로그램이 실행되면 연결버튼을 눌러 서버로부터 문자열을 바당 출력하는지 확인합니다.

Hello World를 확인하셨나요?

네트워크 프로그래밍의 세계에 오신걸 환영합니다^^

그럼 다음시간에 만날 수 있길 바라며 이만 줄입니다.



신고


Posted by injunech
2013.07.05 11:25


이제부터 프로그래밍이라는걸 시작해 보도록 하겠습니다.

대부분 프로그래밍의 처음이 그렇듯이 소켓 프로그램도 마찬가지로 간단한 문자열(Hello World)을 네트워크상에서 출력해 보는 것으로 시작하도록 하겠습니다.

일반적으로 소켓 프로그램은 서비스를 요청하는 클라이언트와 클라이언트의 요청을 받아 서비스하는 서버로 구성됩니다.

지금부터 구현할 소켓 프로그램은 클라이언트 프로그램이 네트워크상에서 통신 채널을 통해 서버측에 연결되면 서버 프로그램이 즉시 문자열을 클라이언트측에 전송하고, 클라이언트 프로그램은 전송받은 문자열을 화면에 출력합니다.

그럼 먼저 서버 프로그램을 구현해 보도록 하겠습니다.
서버 프로그램은 시작 버튼 하나와 상태를 알려주는 스태틱 텍스트로 구성되고, 사용자가 시작 버튼을 누르면 서버가 클라이언트와의 연결을 기다리는 ‘Server Start’라는 상태를 알리게 됩니다.

MFC로 서버 프로그램을 구현할 때 다음의 순서로 진행하도록 하겠습니다.

1 응용 프로그램 마법사로 프로젝트를 만듭니다.
2 소켓으로 사용할 CSocket::CListenSocket과 CSocket::CServiceSocket 객체를 생성합니다.
3 GUI를 설계하고, 각각의 컨트롤에 대해 멤버 함수와 멤버 변수를 추가하고 코딩합니다.
4 클라이언트 프로그램과 연결해서 서버로서의 기능을 검증합니다.

서버 프로그램을 구현하기 위해서 먼저 프로젝트를 생성하겠습니다.
대화 상자 기반으로 고급기능에서 ‘Window 소켓’을 체크하여 프로젝트를 생성합니다.
프로젝트 이름은 HelloServer로 하겠습니다.

저는 Visual Studio 2008을 사용하였습니다.

응용 프로그램 종류에서 대화 상자 기반으로 선택합니다.

고급기능에서 Window 소켓 항목을 체크하고 프로젝트를 생성합니다.

다음으로 소켓 객체(CSocket::CListenSocket과 CSocket::CServiceSocket)의 생성하겠습니다.
CListenSocket 객체는 클라이언트로부터의 연결 요청을 받아들이는 역할을 합니다. 이 객체는 클라이언트의 연결 요청을 받으면 OnAccept 메시지 처리기가 실행되어 연결 요청을 처리합니다.

먼저 MFC 클래스 마법사를 이용하여 CSocket 클래스를 기본클래스로 해서 CListenSocket 객체를 생성합니다.


CListenSocket 객체는 HelloServer 프로젝트의 주 대화 상자 객체와 서로 자료나 메시지를 주고 받으면서 작업해야 합니다. 따라서 프로젝트의 이름으로 HelloServer를 사용하기 때문에 주 대화 상자 객체의 이름은 CHelloServerDlg가 됩니다.

CHelloServerDlg 객체의 시작 버튼을 누르면 CListenSocket 객체를 새로 생성하게 됩니다. CListenSocket 객체로 클라이언트로부터의 연결 요청이 오면, OnAccept 메시지 처리기가 실행되지만 OnAccept 메시지 처리기에서 클라이언트의 연결 요청을 처리하지 않고, 이를 대화 상자 CHelloSeverDlg로 객체로 전달해서 처리하게 됩니다. 따라서 CHelloSeverDlg CListenSocket는 서로의 객체에 대한 주소를 주고 받습니다.

CListenSocket.h 파일을 다음과 같이 작성합니다.

소스 설명은 주석으로 대신 하도록 하겠습니다.

헤더 파일의 작성이 끝났습니다.

다음으로 CListenSocket.cpp을 다음과 같이 구현하겠습니다.

CListenSocket에 대한 준비가 끝났습니다.

다음으로 CListenSocket 객체를 이용하여 클라이언트로부터의 연결 요청을 받아들이고 해당 클라이언트에 대한 처리를 수행할 CServiceSocket 객체를 생성합니다.

CServiceSocket 객체 역시 HelloServer 프로젝트의 주 대화 상자인 CHelloServerDlg 객체와 자료를 송수신하기 위해 서로의 객체에 대한 주소를 주고 받습니다.

ServiceSocket.h을 다음과 같이 작성합니다.

ServiceSocket.cpp을 다음과 같이 구현합니다.

다음으로 GUI설계와 컨트롤에 대한 멤버 함수와 멤버 변수를 추가하도록 하겠습니다.
GUI를 다음과 같이 구성합니다.

HelloServer.h를 작성하도록 하겠습니다. 시작 버튼을 누르면 수행하는 OnBnClickedButtonConnect 메소드를 작성합니다.

CHelloServerDlg.cpp을 다음과 같이 구현합니다.

Hello World를 출력하기 위한 서버프로그램의 준비가 끝났습니다.

이제 빨리 클라이언트 프로그램을 만들어 서버 프로그램과 서로 잘 동작하는지 확인는 일만 남았습니다.

클라이언트 프로그램은 다음 시간에~^^;

그럼 오늘은 여기까지 입니다.

수고하셨습니다.

이 글은 열혈강의 Visual C++ 2008 MFC 윈도우 프로그래밍, 정석용의 TCP/IP 소켓 프로 그래밍 책을 참고하여 작성되었습니다.



신고


Posted by injunech

티스토리 툴바