320 likes | 969 Views
15 장 . 네트워크. TCP/IP 기초를 다진다. MFC를 이용한 소켓 프로그래밍 기법을 익힌다. TCP/IP 개요 (1). TCP/IP 구조. TCP/IP 개요 (2). 계층별 역할 네트워크 액세스 계층 물리적인 신호를 처리하여 실제 데이터를 보내고 받는 네트워크 하드웨어와 장치 드라이버를 포함 인터넷 계층에서 내려 보낸 데이터를 처리하여 통신 상대 (Peer) 에게 보내고 , 통신 상대로부터 받은 데이터를 처리하여 인터넷 계층으로 전달
E N D
15장. 네트워크 TCP/IP 기초를 다진다. MFC를 이용한 소켓 프로그래밍 기법을 익힌다.
TCP/IP 개요 (1) TCP/IP 구조
TCP/IP 개요 (2) • 계층별 역할 • 네트워크 액세스 계층 • 물리적인 신호를 처리하여 실제 데이터를 보내고 받는 네트워크 하드웨어와 장치 드라이버를 포함 • 인터넷 계층에서 내려 보낸 데이터를 처리하여 통신 상대(Peer)에게 보내고, 통신 상대로부터 받은 데이터를 처리하여 인터넷 계층으로 전달 • 물리 주소(Physical Address)를 사용하여 통신을 수행 • 인터넷 계층 • 전송 계층이 내려 보낸 데이터를 네트워크 액세스 계층의 도움을 받아 목적지까지 전달 • IP 주소(Internet Protocol Address)를 이용하여 주소 지정과 라우팅 수행
TCP/IP 개요 (3) • 계층별 역할 (cont'd) • 전송 계층 • 최종적인 통신 목적지 지정 포트 번호(Port Number) 이용 • 데이터를 오류 없이 전송
TCP/IP 개요 (4) • 계층별 역할 (cont'd) • 응용 프로그램 계층 • 다양한 응용 프로그램을 위한 프로토콜을 제공. 전송 계층을 기반으로 만들어진 다수의 프로토콜 포함 • (예) FTP, TELNET, HTTP, ...
응용 프로그램 데이터 TCP TCP 헤더 데이터 IP IP 헤더 TCP 헤더 데이터 이더넷 이더넷 헤더 IP 헤더 TCP 헤더 데이터 이더넷 트레일러 TCP/IP 개요 (5) 인터넷 데이터 전송 과정 - 캡슐화
응용 프로그램 데이터 TCP TCP 헤더 데이터 IP IP 헤더 TCP 헤더 데이터 이더넷 이더넷 헤더 IP 헤더 TCP 헤더 데이터 이더넷 트레일러 TCP/IP 개요 (6) 인터넷 데이터 전송 과정 - 역캡슐화
IP 주소, 도메인 이름, 포트 번호 (1) • IP 주소 • IPv4는 32비트, IPv6는 128비트 숫자 • 8비트 단위로 구분하여 각각 10진수로 표시 • (예) 147.46.114.70 • 전 세계적으로 유일하며, IP 라우팅에 사용됨 • 도메인 이름(Domain Name) • 사람이 기억하고 사용하기 쉬운 이름 • IP 주소로 변환해야 통신 가능
IP 주소, 도메인 이름, 포트 번호 (2) • 포트 번호 • 목적지 프로세스를 지정 ※ IP 주소와 도메인 이름은 목적지 컴퓨터를 지정 • 부호없는 16비트 정수를 사용(0~65535)
프로세스 1 프로세스 2 접속? 접속? 프로세스 1 프로세스 2 접속 대기 클라이언트-서버 모델 클라이언트-서버 모델의 필요성
윈도우 소켓 (1) 소켓 • 소켓 • 다양한 프로토콜을 일관된 인터페이스로 다룰 수 있게 만든 함수 집합 • 윈도우는 API로, 유닉스/리눅스는 시스템 콜로 제공됨
윈도우 소켓 (2) • 윈도우 소켓 • 윈도우 소켓 1.x 버전 • TCP/IP 프로토콜과 버클리 소켓 호환 함수를 주로 지원 • MFC의 소켓 클래스는 윈도우 소켓 1.1 버전만 지원 • 윈도우 소켓 2.x 버전 • 다양한 종류의 프로토콜을 지원하도록 구조를 변경하고 새로운 입출력 함수를 추가하여, 고성능 서버 프로그램 제작을 위한 기능을 제공
MFC 소켓 클래스 MFC 클래스 계층도
MFC 소켓 프로그래밍 - 콘솔 (1) int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { ... AfxSocketInit(); CSocket sock; if(!sock.Create(8000)) ErrQuit(sock.GetLastError()); if(!sock.Listen()) ErrQuit(sock.GetLastError()); char buf[256+1]; int nbytes; 예제 코드 - TCP 서버
MFC 소켓 프로그래밍 - 콘솔 (2) while(1){ CSocket newsock; if(!sock.Accept(newsock)) ErrQuit(sock.GetLastError()); CString PeerAddress; UINT PeerPort; newsock.GetPeerName(PeerAddress, PeerPort); printf("### IP 주소: %s, 포트 번호: %d ###\n", (LPCTSTR)PeerAddress, PeerPort); while(1){ nbytes = newsock.Receive(buf, 256); 예제 코드 - TCP 서버 (cont'd)
MFC 소켓 프로그래밍 - 콘솔 (3) if(nbytes == 0 || nbytes == SOCKET_ERROR){ break; } else{ buf[nbytes] = '\0'; printf("%s", buf, nbytes); } } newsock.Close(); printf("### 접속 종료 ###\n\n"); } ... } 예제 코드 - TCP 서버 (cont'd)
MFC 소켓 프로그래밍 - 콘솔 (4) int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { ... AfxSocketInit(); CSocket sock; if(!sock.Create()) ErrQuit(sock.GetLastError()); if(!sock.Connect("127.0.0.1", 8000)) ErrQuit(sock.GetLastError()); char buf[256]; int nbytes; 예제 코드 - TCP 클라이언트
MFC 소켓 프로그래밍 - 콘솔 (5) for(int i=0; i<5; i++){ wsprintf(buf, "%d번째 테스트 메시지\r\n", i); nbytes = sock.Send(buf, 256); if(nbytes == SOCKET_ERROR) ErrQuit(sock.GetLastError()); else{ printf("<%d> %d바이트 전송\n", i, nbytes); Sleep(1000); } } sock.Close(); ... } 예제 코드 - TCP 클라이언트 (cont'd)
주요 함수 (1) BOOL CSocket::Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, LPCTSTR lpszSocketAddress = NULL ); BOOL CAsyncSocket::Listen(int nConnectionBacklog = 5); 서버 코드
주요 함수 (2) BOOL CAsyncSocket::Accept( CAsyncSocket& rConnectedSocket, SOCKADDR* lpSockAddr = NULL, int* lpSockAddrLen = NULL ); BOOL CAsyncSocket::GetPeerName( CString& rPeerAddress, UINT& rPeerPort ); 서버 코드 (cont'd)
주요 함수 (3) int CAsyncSocket::Receive( void* lpBuf, int nBufLen, int nFlags = 0 ); void CAsyncSocket::Close(); 서버 코드 (cont'd)
주요 함수 (4) BOOL CAsyncSocket::Connect( LPCTSTR lpszHostAddress, UINT nHostPort ); int CAsyncSocket::Send( const void* lpBuf, int nBufLen, int nFlags = 0 ); 클라이언트 코드
동기와 비동기 개념 (1) • 비동기 함수 오류 메시지 • 동기와 비동기 함수의 특성 • 동기(Synchronous = Blocking) 함수 • 작업 처리 조건이 만족될 때까지 함수가 리턴하지 않고 대기한다. • 비동기(Asynchronous = Nonblocking) 함수 • 작업 처리 조건이 만족될 때까지 함수가 대기하지 않고 리턴한다.
동기와 비동기 개념 (2) void CMyTestView::OnLButtonDblClk(UINT nFlags, CPoint point) { ... char buf[256]; socket.Recv(buf, 256); // 받은 데이터가 없으면 여기서 // 메시지 루프가 정지된다. } • 동기 함수의 문제점 • 해결 별도의 스레드를 만들어서 동기 함수를 호출하거나 비동기 함수를 사용해야 한다.
동기와 비동기 개념 (3) • CSocket 클래스 • 중요 함수의 경우 동기적으로 동작하되, 함수 호출 시 메시지 루프가 정지하는 일이 없도록 내부적으로 윈도우 메시지를 처리 • (예) Accept(), Receive(), Send(), Connect(), ReceiveFrom(), SendTo() • 동기 함수를 호출해야 할 시점을 가상 함수 호출로 알려줌. CAsyncSocket 클래스가제공하는 On~ 함수를 정의해 두면 자동으로 해당 On~ 함수가 호출됨. • (예) 클라이언트가 접속하면 가상 함수 OnAccept()가 자동으로 호출됨. 따라서OnAccept() 함수를 재정의하고 여기서 Accept() 함수를 호출
MFC 소켓 프로그래밍 - GUI • CSocket 클래스를 이용한 응용 프로그램 작성 • CSocket 클래스를 상속받아 새로운 소켓 클래스를 생성 • CAsyncSocket 클래스가 제공하는On~ 가상 함수를 필요에 따라 재정의 • 재정의한 On~ 가상 함수에서 적절한 소켓 함수를 호출 • (예) OnAccept() 함수에서는 Accept() 함수를 호출하고, OnReceive() 함수에서는 Receive() 함수를 호출
직렬화를 이용한 소켓 입출력 (1) CSocket sock; UINT data1; CString data2; ... CSocketFile file(&sock); CArchive ar(&file, CArchive::store); ar << data1; ar << data2; 데이터를 보내는 경우
직렬화를 이용한 소켓 입출력 (2) CSocket sock; UINT data1; CString data2; ... CSocketFile file(&sock); CArchive ar(&file, CArchive::load); ar >> data1; ar >> data2; 데이터를 받는 경우
직렬화를 이용한 소켓 입출력 (3) 직렬화를 이용한 소켓 입출력 과정
직렬화를 이용한 소켓 입출력 (4) • 장점 • 입출력 함수를 직접 사용하지 않으므로 프로그래머가 입출력과 관련된 세부 사항을 신경쓰지 않아도 됨 • 통신 양단의 문자열 저장 방식이 달라도 내부적으로 변환하여 올바로 처리 • 통신 양단의 바이트 정렬(Byte Ordering)이 달라도 내부적으로 변환하여 올바로 처리
직렬화를 이용한 소켓 입출력 (5) • 단점 • 통신 양단이 모두 MFC의 직렬화를 이용한 소켓 입출력을 하는 경우에만 올바른 데이터 교환이 보장됨 • CSocket 클래스 대신 CAsynSocket 클래스를 직접 사용할 경우에는 직렬화를 쓸 수 없음
Thank you www.hanb.co.kr