본문 바로가기

TIPS/MFC

[TIPS} 15th 20160825

15번째 강좌 정리입니다~


<간단한 채팅 프로그램 만들기_서버(3)>


지난시간 설명한 것처럼 "abc"를 보낸다면 뒤에 0까지 해서 4byte를 보내는데, 그것만 보내지 않고 헤더를 붙여야 한다.

즉 27, 1 ,4(2byte), "abc"로 4+4 바이트를 보내야 한다.


따라서 이 부분은 함수를 따로 하나 만들어줄 것이다.


-SendFrameData 함수 작성하기


이와같이 만들고 헤더파일에도 추가해준다.


메모리를 동적할당할때는 항상 반환을 함께 써주는 습관을 들여야한다.




a_body_size가 들어가는 부분을 생각해보자. 사이즈가 255이하일 경우에는 리틀엔디언을 쓰기 때문에 정상적으로 작동할수는 있지만 그 이상일 경우에는 오류가 나게된다. 따라서 위와 같이casting을 해주는 것이다!!



위와 같이 메모리카피함수와 전송함수를 추가하여 함수작성을 마친다.


이와 같이 메모리의 그림을 그리고 순차적으로 코드를 작성하는 과정을 잘 연습해야한다!


<간단한 채팅 프로그램 만들기_클라이언트>




1. 프로젝트를 만들어준다.

2. 대화상자 속성에서 글꼴을 "굴림 보통 9"로 바꾸어준다.

3. 리스트박스를 하나 만들어 준다.

 

4. 위 캡쳐와 같이 변수도 추가해준다.


5. edit control와 버튼을 하나씩 추가해준다.


버튼은 이름을 IDC_SEND_BTN로 변경하고 캡션을 고쳐준다. 더블클릭하여 함수를 만들어준다.

대화상자는 아래와 같은 상태가 된다.



6. 프로젝트 속성에서 문자집합 사용안함으로 설정한다.



7. 소켓을 사용하기 위해 13번째 강의에서와 같이 헤더파일과 소스파일에 라이브러리를 각각 추가해준다. #pragma comment (lib, "WS_32.lib")


8. Instance함수를 필요한 것만 남기고 삭제하여 정리하고

WSADATA temp;//

WSAStartup(0x0202, &temp);//

WSACleanup();// 를 추가해준다.


9. 프로젝트명Dlg.h에

private:

SOCKET mh_socket = INVALID_SOCKET;

를 추가해준다. 여기에는 자동적으로 -1이 들어간다. 마우스를 올려보면 '~0'으로 표시되어 있는 것을 볼 수 있다. (-1이나 0x등으로 표기하지 않고 ~0으로 표기되는 이유는 32비트 운영체제이든 64비트 운영체제이는 소스코드에는 영향이 가지 않기 때문이다.)


10. 프로젝트명Dlg.cpp에서 OnInitDialog()함수로 온다.

mh_socket = socket(AF_INET, SOCK_STREAM, 0);를 추가해주고


struct sockaddr_in srv_addr;

memset(&srv_addr, 0, sizeof(struct sockaddr_in)); //이는 구조체를 모두 0으로 채우기 위해 적어준 것으로 꼭 넣어줄 필요는 없다.

srv_addr.sin_family = AF_INET;

srv_addr.sin_addr.s_addr = inet_addr("10.104.192.26"); //접속할 서버 아이피

srv_addr.sin_port = htons(18000);


를 추가해준다.


11. connect(mh_socket, (LPSOCKADDR)&srv_addr, sizeof(srv_addr));

이는 1. 네트워크가 연결되어있어야 하고 2. 서버가 실행되어 있어야 하고 3. listen이 가능해야한다.


만약 connect가 실패를 하면 28초동안 응답없음으로 다운된다.

이를 회피하기 위해서 WSAAsyncSelect(mh_socket, m_hWnd, 25001, FD_CONNECT);를 추가해준다.

FD_CONNECT라면 m_hWnd에 25001메세지를 준다는 의미이다.


클라이언트는 connect에 시간이 걸리기 때문에

1. 서버에 접속하지 않았다, 2. 서버에 접속중이다, 3. 서버에 접속이 되었다. 이렇게 세가지 상태로 나뉜다.


12. 프로젝트명dlg.h에 와서

char m_connect_flag = 0; //0:접속해제, 1: 접속중, 2: 접속됨

소켓만으로는 상태를 받지 못하기 때문에 이러한 변수를 추가해준다.


13. 프로젝트명dlg.cpp로 돌아와서 

m_connect_flag = 1;를 추가해준다.


14. 클래스 마법사에서 메세지 ondestory를 추가하여

void CExamClientDlg::OnDestroy()

{

CDialogEx::OnDestroy();


if (mh_socket != INVALID_SOCKET) {

closesocket(mh_socket);

mh_socket = INVALID_SOCKET;

}

}

작성해준다.


15. 클래스마법사에서 25001이라는 사용자메세지를 추가해준다.


16. 

void CExamClientDlg::AddEventString(const char *sp_string)

{

while (m_chat_list.GetCount() > 500) {

m_chat_list.DeleteString(0);

}

int index = m_chat_list.InsertString(-1, sp_string);

m_chat_list.SetCurSel(index);

}

도 추가해주고



17. connect함수에

AddEventString("서버에 접속을 시도합니다...");

도 추가해준다.


18. 25001메세지에도 이벤트스트링을 넣어준다.

(잠깐 서버 코드로 돌아와 지난시간에 빠뜨린 

CString str;

str.Format("%s에서 접속했습니다.", m_user_list[i].ip_address);

AddEventString(str); 도 추가해준다.)


19. 클래스 마법사에서 25002메세지를 추가해준다.(서버 코드에서 복붙!!)

else부분만

else {

closesocket(mh_socket);

mh_socket = INVALID_SOCKET;

m_connect_flag = 0;

AddEventString("서버가 연결을 해제했습니다~");

}

이렇게 수정해준다.


20. 다시 server에서 만들었던 sendframedata함수를 복붙해준다!


22. 서버의 25001함수의 if(key==27)조건문에 


위의 코드를 추가해준다.


23. 참고로 현재 상태에서는 엔터를 치면 '확인'버튼이 활성화되어 있어서 닫혀버린다.

(확인버튼이 활성화된 것을 볼 수 있다.)


이는 버튼의 속성에서 Default Button부분을 False로 바꿔주고 전송버튼을 True로 바꾸어 주면 엔터의 입력으로 채팅이 입력된다.




24. 여기까지는 채팅을 입력하면 입력한 것이 그대로 있다. 채팅을 지워지도록 설정할 수도 있지만,

즉, 주석처리 되어있는 것처럼 표현해줄 수 있지만 (이는 하수들이 하는 방법..!) 

그 아래의 줄처럼 블럭을 잡도록 작성해주면 훨씬 편리한 기능을 수행하게 된다. 


이로써 채팅프로그램을 완성하였다!





www.tipssoft.com


'TIPS > MFC' 카테고리의 다른 글

[TIPS] 13th 20160818 (list box / socket)  (0) 2016.08.20
[TIPS] 11th 20160808  (0) 2016.08.20
[TIPS] 10th 20160804  (0) 2016.08.20