'socket'에 해당되는 글 1건

  1. 2004.07.22 소켓 프로그래밍 기초

1. 소켓 프로그래밍 기초

 

(1)    윈속과 TCP/IP

윈속이라는 API TCP/IP 지원하며, 추후 다른 프로토콜도 지원할 있다.

 

응용 프로그램

윈속API  (WINSOCK.DLL)

TCP/UDP

IP

이더넷

*물리계층, Data Link계층, 네트웍 계층, Transport Layer : 시스템 O/S에서 처리.

 (세션 계층, Presentation Layer) Application Layer : 소켓 프로그래밍.

 

(2)    Client & Server 형태로 동작

서버쪽 프로세스는 초기화 과정을 거친 클라이언트의 요구를 받기 위한 상태로 대기한다. 이때 클라이언트의 요청을 받기 위한 특정 포트(port)번호가 할당되며, 서버 프로세스는 포트를 감시한다. 클라이언트가 서버의 주소와 포트로 데이터를 보내면 서버는 대기상태에서 깨어나 해당 서비스를 수행한다. 소켓은 양방향 전송을 지원하기 때문에 하나의 소켓을 열면 이를 통해 데이터를 보내는 기능과 받는 기능을 동시에 수행할 있다.

 

(3)    연결형과 비연결형

1)    연결형 (Connection-Oriented)

a. Stream Socket이라고도 하며 TCP프로토콜 사용.

b. 신뢰성이 있고, 다량의 데이터 전송에 적합.

c. Packet 보내어진 순서대로 중복 없이 도착되도록 보장 받는다.

d. 패킷 경계선이 없는 계속적인 양방향 스트림 데이터를 주고 받는다.

  [ 4계층인 TCP 연결 설정된 상대방 주소와 포트를 관리하여 받은 패킷의 상대방 주소와 포트가 연결 설정된 같으면 주소, 포트 정보를 데이터만 상위 계층에 올려보내고 틀리면 패킷은 버린다.  TCP 상위 계층은 상대 주소, 포트 정보 없이 데이터가 스트림으로 전달된다. ]

 

2)    비연결형 (Connectionless)

a. Datagram Socket이라고도 하며 UDP 프로토콜 사용

b. 신뢰성이 없고, 소량의 데이터 전송에 적합

c. 효율적인 네트웍 사용 (연결형보다 빠른 속도)

d. Packet 보내진 순서대로 도착하지 않을 수도 있으며 중복 또는 아예 도착하지

수도 있다.  그래서 패킷의 데이터 헤더에 보내는 데이터가 번째 블록인지

정해서 보내야 상대방이 순서대로 정열할 있음. (응용 프로그램에서 처리)

e. 패킷 단위로 데이터가 끊어져서 읽히게 된다.

  [ 4계층의 UDP 연결 설정된 주소 포트가 없으므로 포트로 도착한 모든

(상대방 주소, 포트 포함) 그대로 상위 포트에 올려보낸다.  UDP 상위 계층은

패킷 크기로 Datagram 전달된다.  

*, recvfrom(), sendto() 이용할 때마다 상대편 주소와 포트정보를 주고받아야 한다.

 

(4)    소켓 통신을 위한 5가지 기본 요소

프로토콜 :           연결형(TCP) or 비연결형(UDP)

자신의 주소 :   Host구분

자신의 포트 :   Host내의 Process구분

상대방 주소 :

상대방 포트 :

 

(5)    버클리 소켓과 윈속의 차이

윈속은 버클리 소켓을 대부분 따른다.

, 블록킹 문제를 해결하기 위해 Windows Event-Driven특성을 살려 비동기용 확장 함수를 추가하였다.

 

(6)    블록킹 (Blocking)

블록킹 상태이면 블록킹된 함수가 결과를 리턴하고 끝마칠 때까지 제어권이 돌아오지

않는다. , 다른 응용 프로그램이 이상 실행될 없게 된다.

비블로킹 상태이면 함수를 실행하는 동안에도 프로그램은 계속해서 사용 가능하다.

소켓을 생성하면 기본적으로 블록킹 상태로 동작한다. 윈도우 상에서는 함수를 블로킹

상태로 호출하는 경우 이벤트를 받을 없게 된다.

 

Ex) recv()함수를 호출해 소켓으로부터 10Byte 데이터를 읽으려고 하는 경우 수신 버퍼에 도착한 데이터가 없다면, 읽어 들일 데이터가 도착하거나 또는 연결이 끊어져 오류가 발생할 때까지 recv()함수로부터 제어가 돌아오지 않는다.

*해결 방안

a.   블록킹 (Blocking Hook)

Windows 프로그램이 GetMessage() PeekMessage()등을 호출할 때만 작업 전환을 하므로 블록킹은 시스템 전체를 정지시킬 위험이 있다. 이를 막기 위해 윈속에서는 블록킹 가능성이 있는 윈속API 호출하면 무한 루프를 돌면서 BlockingHook() 호출한다.

 

b.   비블록킹 (non-blocking) 상태 설정

소켓을 새로 열면 처음에는 블록킹 상태로 동작하지만, 이를 비블럭킹 상태로 전환할 수도 있다. 비블럭킹 상태에서는 요구된 작업을 즉시 종료할 없을 블록킹되는 대신에 바로 리턴해 버린다. (그리고, 관련 함수를 계속 호출)

소켓의 블록킹 상태 전환 : ioctlsocket()함수 사용.

 

  *위의 방법은 사용자 프로그램에서 루프를 돌면서 특정 상황이 발생하기를 계속 검사해야 하므로 상당히 비효율적이다.                 

 

(7)    비동기 함수 (Asynchronous Function)

Windows 프로그램은 기본적으로 메시지를 받아서 그에 해당하는 작업을 처리하는 형태로 동작하므로 네트워킹에 관련된 작업도 특정 사건이 발생했을 메시지를 받아 처리하도록 지원하기 위한 것이 비동기 함수이다. , 수신된 데이터가 있는지를 되풀이해서  검사해 보는 것이 아니라, 데이터 수신이라는 사건이 발생하면 시스템에서 자동으로 메시지를 윈도우 프로시저에 보내는 방식이다.

 

(8)    바이트 순서 (Byte Order)

프로세서에 따라 메모리에 데이터를 저장하는 방식이 다르기 때문에 시스템에서는 문제가 없지만 다른 저장 방식을 사용하는 시스템과 통신을 하는 경우는 문제가 된다.

char 같은 1Byte 데이터는 그냥 전송하면 되지만 short (2Byte) long(4Byte) 같은 데이터는 변환이 필요하다.

 

Host Byte Order

 : Little Endian이라고도 하며, 하위 바이트를 낮은 주소에 저장

 Ex) 인텔 x86계열 프로세서

 

네트워크 바이트 순서 (N/W Byte Order)           소켓 통신 표준

 : Big Endian           상위 바이트를 낮은 주소에 저장

                      Ex) 모토로라 68000계열

 

*바이트 순서 변환 함수

 htons ( u_short hostshort );

 ntohs ( u_short netshort );

 

2. 윈속 지원 클래스

 

MFC에서는 WinSock 관련된 많은 API 추상화한 3가지 소켓 관련 클래스를 제공.

 

CAsyncSocket                  비동기 통신 지원

CSocket                     동기 통신 지원

CSocketFile                  N/W 상으로 전송할 데이터를 파일처럼 취급. 직렬화 활용.

 

계승도.

(1) CObject – CAsyncSocket

 1) 블록킹 문제 해결 :                   비동기 모드 함수 사용하여 데이터 교환

 2) Byte Order 문제 :     ntoh~(), hton~()함수를 사용하여 네트워크 바이트 순서로 바꾸어 전송하고 데이터를 받을 때도 호스트 바이트 순서로 바꾸어 받아야 한다.

( char 1 byte 데이터는 상관없지만 2byte이상의 데이터 (정수형, 실수형 ) 바이트 순서 처리를 해주어야 한다.)

 

(2) CObject – CAsyncSocket - CSocket

 데이터를 보내고 받는 것을 관리하는 클래스 CSocketFile CArchive 함께 동작한다.

 블록킹 된다.

 

CObject - CFile - CSocketFile

 

 


3. MFC 이용한 소켓 프로그래밍.

CAsyncSocket 이용한 연결형 통신 구조

 

서버 영역 프로그래밍                                                                        클라이언트 영역 프로그래밍

 

*중심 소켓 : 계속해서 새로운 클라이언트를 기다림.

 

//객체 생성 ( Stack상에 구현 )                                             //객체 생성

CAsyncSocket* pSocket = new CAsyncSocket ;                                     

 

// port 2000번으로 서버 소켓 생성                                            //클라이언트 소켓 생성

pSocket->Create(2000);  //default : Stream Socket                        pSocket->Create();

[ 비연결형  pSocket->Create( 2000, SOCK_DGRAM );                // Datagram Socket생성 ]

 

pSocket->Listen();                  //Client접속 기다림.

 

*자식 소켓 생성

                                                                                                            //서버의 IP & Port No 접속 설정

CAsyncSocket  Sock;                                                              pSocket->Connect(Adr, 2000);

 

//자식 소켓에 현재 연결이 들어온

클라이언트 연결시켜줌                                   

PSocket->Accept(Sock);                                                                        

 

//클라이언트와의 data통신

Sock.Send( “안녕!” );                                                            pSocket->Receive(data);

 

Sock.Receive( data );                                                                  pSocket->Send(“나도 안녕”);

 

*Event처리

 

OnAccept : 클라이언트가 Connect 실행하여 서버에 접속하고자 서버에서는 새로운 클라이언트가 들어오면 OnAccept함수가 실행된다.

 

OnReceive : 새로운 데이터가 들어왔을 경우에는 OnReceive라는 함수가 실행된다.


Posted by 노을삼킨별
,