티스토리 뷰
1부 : 윈도우즈 MFC 소켓프로그래밍 : 소켓 기본 클래스 소스코드 1 (헤더파일)
http://andrew0409.tistory.com/97
2부 : 윈도우즈 MFC 소켓프로그래밍 : 소켓 기본 클래스 소스코드 2 (서버cpp파일)
http://andrew0409.tistory.com/99
3부 : 윈도우즈 MFC 소켓프로그래밍 : 소켓 기본 클래스 소스코드 3 (클라이언트cpp파일)
http://andrew0409.tistory.com/100
소켓 기본 마지막 포스팅. 오늘은 지금까지 배운 CServerSocket과 CClientSocket을 이용해서 직접 서버에 연결하고 데이터를 전달해보는 예제 소스코드를 보고 연습해보겠다.
1 2 3 4 5 6 7 8 9 10 11 12 | void CChildView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { if (mServer.Create(26000) == false) { MessageBox(L"서버가 구동 중입니다.", L"에러", MB_ICONERROR); return; } MessageBox(L"클라이언트를 기다리고 있습니다.", L"알림", MB_ICONINFORMATION); AfxBeginThread(ServerProc, this); } | cs |
우선 키 다운 메세지를 통해서 키보드로부터 어떤값이든 입력을 받으면 서버가 구동되도록 간단하게 코딩했다.
서버소켓이 생성되고 클라이언트를 기다리고있다는 메세지를 띄워주고 나면 쓰레드를 통하여 서버를 실행한다. 쓰레드를 사용하는 이유는.. 쓰레드를 사용하지 않으면 해당 단계에서 서버는 listen->accept를 하면서 connect가 들어올때까지 멈춰서 다른 조작을 할 수 없다. 그것은 서버가 Blocking 소켓이기 때문인데 (반대는 Non Blocking 소켓) 이에 대해서는 아마 다음이나 그다음 포스팅쯤에서 다뤄보는게 어떨까 하고 계획하고 있다.
간략하게만 소개를 하겠다.
블로킹, 논블로킹을 소켓모드라고 칭하는데, 소켓은 소켓 함수 호출시 동작 방식에 따라 블로킹 혹은 논블로킹 소켓으로 구분 할 수 있다.
⊙ 블로킹 소켓
소켓 함수 호출시 조건이 만족되지 않으면 함수는 리턴하지 않고 해당 스레드는 대기 상태가 된다.
소켓 함수는 리턴하지 않으므로 멀티스레드를 사용하여 다른 작업을 하지 않는 한 애플리케이션이 더는 진행할 수 없다. socket() 함수는 기본적으로 블로킹 소켓이다.
⊙ 넌블로킹 소켓
소켓 함수 호출시 조건이 만족되지 않더라도 함수가 리턴하므로 해당 스레드는 계속 진행할 수 있다.
넌블로킹 소켓의 장점이라면 소켓 함수 호출시 블록되지 않으므로 다른 작업을 진행할 수 있기 때문에 멀티스레드를 사용하지 않고도 여러개의 입출력을 처리할 수 있다는 점이지만, 해당 함수를 호출할 때마다 WSAEWOULDBLOCK등 오류코드를 확인해서 처리하고, 다시 해당 함수를 호출해야 하므로 프로그램 구조가 복잡해지며, 블로킹 소켓을 사용한 경우보다 CPU 사용률이 높다.
우리가 만들었던 서버소켓은 socket() 함수를 통하여 생성되었기 때문에 블로킹 소켓이다. 따라서 ServerProc에서 accept를 진행하면 Connect가 들어올때까지 프로그램은 멈춰있게 된다. 이제 서버 프로시저를 살펴보겠다.
1 2 3 4 5 6 7 8 9 10 11 12 | UINT ServerProc(void *p) { CChildView* view = (CChildView*)p; while (true) { SOCKET client = view->mServer.Accept(); AfxBeginThread(ClientProc, new PARAM(view, client)); } return 0; } | cs |
1 2 3 4 5 6 7 | struct PARAM { CChildView *view; SOCKET sock; PARAM(CChildView *v, SOCKET s) : view(v), sock(s) {} }; | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | UINT ClientProc(void *p) { PARAM param = *(PARAM*)p; delete (PARAM*)p; std::vector<CPoint> *current = nullptr; std::vector<std::vector<CPoint> * > path; CClientDC dc(param.view); CClientSocket client; client.Attach(param.sock); char buf[256]; int recvd = 0; while (true) { int ret = client.Recv(buf + recvd, sizeof(buf) - recvd); if (ret == SOCKET_ERROR || ret == 0) break; recvd += ret; int pos = 0; while (true) { if (recvd - pos < 12) // 데이터 크기 { memcpy(buf, buf + pos, recvd - pos); recvd -= pos; break; } int *p = (int*)(buf + pos); TRACE(L"[%d] %d, %d\n", p[0], p[1], p[2]); CPoint point{ p[1], p[2] }; if (p[0] == CChildView::DRAW_START) { current = new std::vector < CPoint >; current->push_back(point); } else if (p[0] == CChildView::DRAW_END) { path.push_back(current);; current = nullptr; } else if (p[0] == CChildView::DRAW_MOVE) { if (current == nullptr) break; current->push_back(point); dc.Polyline(&(*current)[0], current->size()); } pos += 12; } } return 0; } | cs |
1 2 3 4 5 6 7 | void CClientSocket::Attach(SOCKET sock) { if (IsValid() == true) Close(); mSock = sock; } | cs |
1 | int ret = client.Recv(buf + recvd, sizeof(buf) - recvd); | cs |
1 2 3 4 5 6 | if (recvd - pos < 12) // 데이터 크기 { memcpy(buf, buf + pos, recvd - pos); recvd -= pos; break; } | cs |
1 | int *p = (int*)(buf + pos); | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | CPoint point{ p[1], p[2] }; if (p[0] == CChildView::DRAW_START) { current = new std::vector < CPoint >; current->push_back(point); } else if (p[0] == CChildView::DRAW_END) { path.push_back(current);; current = nullptr; } else if (p[0] == CChildView::DRAW_MOVE) { if (current == nullptr) break; current->push_back(point); dc.Polyline(&(*current)[0], current->size()); } | cs |
1 2 3 4 5 6 | if (recvd - pos < 12) // 데이터 크기 { memcpy(buf, buf + pos, recvd - pos); recvd -= pos; break; } | cs |
'C,C++' 카테고리의 다른 글
소켓 프로그래밍 : 소켓을 이용한 채팅 프로그램 만들기 예제(서버) (3) | 2015.06.25 |
---|---|
윈도우즈 MFC 소켓프로그래밍 : 소켓 기본 클래스 소스코드 5 (클라이언트 메인.cpp) (1) | 2015.06.25 |
윈도우즈 MFC 소켓프로그래밍 : 소켓 기본 클래스 소스코드 3 (클라이언트cpp파일) (0) | 2015.06.25 |
윈도우즈 MFC 소켓프로그래밍 : 소켓 기본 클래스 소스코드 2 (서버cpp파일) (1) | 2015.06.24 |
윈도우즈 MFC 소켓프로그래밍 : 소켓 기본 클래스 소스코드 1 (헤더파일) (2) | 2015.06.23 |
- Total
- Today
- Yesterday
- UML
- 안드로이드
- 데이터베이스
- 액터
- C++
- 클라이언트
- 리눅스
- 프로세스
- 쓰레드
- 소켓 프로그래밍
- 유즈케이스
- 디렉터리
- 악보
- C
- 파이썬예제
- 클래스
- 스레드
- 티라노 시그널
- 정렬
- MFC
- Sort
- socket
- 파일
- 터미널
- 자료구조
- C/C++
- 소켓
- 파이썬
- 라즈베리파이
- 티그널
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |